如何将Swift结构体作为参数传递给Objective-C方法

12

我有一个接受类型为id的参数的Objective-C方法,我想传递一个Swift结构体。

ObjcClass.m文件:

@implementation ObjcClass
+ (void)addListener:(id)listener {
    // Do something with listener
}

DemoStruct.swift 文件:

struct DemoStruct {
    func registerAsListener() {
        ObjcClass.addListener(self) // Can't find a way to do this
    }
}

我得到的编译错误信息如下:

类型“DemoStruct”不符合协议“AnyObject”

所以我的问题是,如何使Objective-C方法接受Any而不是AnyObject,并且是否存在这样的方法?
3个回答

15
我发现最好的方法是将其包装在一个Box类中。
public class Box<T> {
    let unbox: T
    init(_ value: T) {
        self.unbox = value
    } }

1
哇,这是一个优雅的解决方案。Xcode 7 beta 3。我不得不子类化NSObject。 - neoneye
@neoneye和Edward,你们如何将它作为NSObject的子类?我一定做错了什么吗?public class Box<T>:NSObject不是吗? - Fattie

12

你无法做到。

Swift结构体无法从Objective-C中访问。这在苹果的《使用Swift与Cocoa和Objective-C》一书中得到说明:

只要符合Objective-C兼容性,您就可以访问带有@objc属性的类或协议中的任何内容。这不包括仅Swift的功能,例如以下功能:

  • 泛型
  • Tuple元组
  • 在Swift中定义的枚举
  • 在Swift中定义的结构体
  • 在Swift中定义的顶级函数
  • 在Swift中定义的全局变量
  • 在Swift中定义的类型别名
  • Swift样式的可变参数
  • 嵌套类型
  • 柯里化函数

摘自:苹果公司。“使用Swift与Cocoa和Objective-C。”iBooks。 https://itun.es/gb/1u3-0.l


谢谢@jrturton,可能一个好的方法是绕过它?也许一个虚拟包装器类呢? - Edward Ashak
也许,或者你可以传递出一个适用于Objective-C的友好表示。这取决于你在Objective-C领域需要它用来做什么。 - jrturton
关于枚举功能的可用性已经进行了修订:“在Swift中定义的不带Int原始值类型的枚举”。 - Dmytro Hutsuliak

0
补充 Edward Ashak 的回答,我们可以使用以下扩展。因此,在 Objective-C 部分的某个地方可以声明一个容器属性:
// An object that holds our Swift struct instance:
@property (nonatomic, strong) NSObject* pocObject;

在 Swift 部分,我们声明结构体本身和一堆辅助函数:
// The struct we are boxing inside pocObject:
struct POCWithCheck: Decodable {
 ...
}

@objc class POCWithCheckBox: NSObject {
  let unbox: POCWithCheck
    init(_ value: POCWithCheck) {
      self.unbox = value
    }
}

extension POCWithCheck {
  func asNSObject() -> NSObject {
    return POCWithCheckBox(self)
  }
}

extension NSObject {
  func asPOCWithCheck() -> POCWithCheck? {
    return (self as? POCWithCheckBox)?.unbox
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接