我正在跟踪Swift和Objective-C Runtime,它适用于常规方法。
我喜欢使用init方法,据我了解,init就像一个类方法。因此,我尝试将初始化作为实例和类方法。但这似乎不起作用
我可以使用Objective C使其工作,只是想知道如何在Swift中使其工作
摘录自我的要旨
dispatch_once(&Static.token) { let originalSelector = Selector("init:source:destination:") let swizzledSelector = Selector("ftg_init:source:destination:") let originalMethod = class_getClassMethod(self, originalSelector) let swizzledMethod = class_getClassMethod(self, swizzledSelector) let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) if didAddMethod { class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }
为方法创建选择器时,应使用Obj C方法签名作为选择器的基础,因为使用Obj C运行时完成了模糊处理。
所以原来的选择器应该是
initWithIdentifier:source:destination:
现在,这有点奇怪,因为定义了init方法,因此第一个参数上的标签是必需的(identifier两次),所以实际上要使用的选择器是
identifier
ftg_initWithIdentifier:source:destination:
我能找到的唯一文档是关于从Obj C到Swift的翻译的,但看起来好像是从Swift到Obj C的相反。
接下来,init...是一个实例方法,因此您需要进行两项更改。您需要更改class_getClassMethod为class_getInstanceMethod并且需要class从ft_init...方法中删除。
init...
class_getClassMethod
class_getInstanceMethod
class
ft_init...
因此,当所有事情都说完之后,您的代码应该看起来像这样(对我有用)
dispatch_once(&Static.token) { let originalSelector = Selector("initWithIdentifier:source:destination:") let swizzledSelector = Selector("ftg_initWithIdentifier:source:destination:") let originalMethod = class_getInstanceMethod(self, originalSelector) let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) if didAddMethod { class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } func ftg_init(identifier identifier: String!, source: UIViewController, destination: UIViewController) -> UIStoryboardSegue { return ftg_init(identifier: identifier, source: source, destination: destination.ftg_resolve()) }