如何从 Swift 调用 Objective-C 类的工厂方法?
Posted
技术标签:
【中文标题】如何从 Swift 调用 Objective-C 类的工厂方法?【英文标题】:How to call a factory method of an Objective-C class from Swift? 【发布时间】:2014-10-19 16:20:05 【问题描述】:我有一个 obj-c 类,它使用工厂方法将自己实例化为单例。我将该类添加到我的 Swift 桥头文件中,并希望从 swift 类中调用此工厂方法。但是,XCode 不会让我这样做。
obj-c代码是:
@interface MOAssistant : NSObject
...
+ (MOAssistant *)assistant;
@end
Swift 代码是:
let assistant = MOAssistant.assistant;
使用此代码我得到错误:
'assistant()' 不可用:使用对象构造'MOAssistant()'
我读到了mapping factory methods to Swift initializers,但我想知道为什么我可以简单地使用:
let fm = NSFileManager.defaultManager;
尽管 defaultManager 也是一个工厂方法。这令人困惑。我在这里阅读了其他类似这样的帖子:
How are Objective-C factory methods converted into Swift convenience initializers? Create Swift instance from Objective-C factory method但他们都没有解释为什么 Swift 行为不同。使用推荐的方式 (MOAssistant()
) 不是解决方案,因为它直接调用该类的初始化程序(我不想要)。
【问题讨论】:
你不应该使用 NSFileManager.defaultManager 而不让它成为一个函数调用;它应该是 NSFileManager.defaultManager()。 这很奇怪,我可以。但它看起来会产生一些意想不到的东西(可能是代理对象或其他一些引用,lldb 输出看起来像一个修饰名称)。 它可能创建的是对函数的引用。 如果您将工厂方法从assistant
重命名为其他名称,它将正常工作。单例的常见约定是以shared
开头的名称,例如sharedAssistant
。
NSFileManager.defaultManager 没有括号是一个闭包。它是有效的,只是不是人们认为的那样。 fm 是一个闭包, fm() 将是默认的文件管理器。就像每个没有括号的旧 C 函数一样,它是一个“函数指示符”,可以分配给函数指针,但不能分配给函数调用。
【参考方案1】:
像往常一样:很好地解释您的问题,您可能会自己找到答案。这是一个命名的问题。通过将工厂方法重命名为 defaultAssistant 之类的其他名称或 makeThisInstanceForMe 之类的无关名称,我可以轻松地从 Swift 访问它。看起来 swift 标头创建者删除了大写字母以查看它是否与函数名称相同(不区分大小写),如果是这种情况,则使其成为 Swift 初始化程序调用而不是类函数。
但是,请记住将工厂方法调用为方法/函数(包括括号),否则您会得到其他东西,但不是您所期望的。如果你指定了一个类型,你实际上不能没有它。
不使用括号时的 LLDB 输出:
(lldb) po 助手
(Pecunia`_TPA__TTOFCSo11MOAssistant8makeThisfMS_FT_GSQS__ 在 RemoteResourceManager.swift)
这个问题实际上揭示了另一个危险的问题,如果你使用自动/弱类型,你会遇到这个问题。弱类型语言被认为很危险是有原因的,尽管它们很方便。
【讨论】:
查看developer.apple.com/library/ios/documentation/swift/conceptual/…以上是关于如何从 Swift 调用 Objective-C 类的工厂方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何从具有隐藏变量名称(参数前的_)或内部+外部(例如 foo(with bar:))的 Objective-C 调用 Swift 函数
将json调用语法从Objective-C转换为Swift的正确方法是啥?
使用完成处理程序(闭包)语法从objective-c文件调用swift文件中的函数