一尘不染

如何在Swift中初始化init

swift

我正在跟踪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);
            }
        }

阅读 219

收藏
2020-07-07

共1个答案

一尘不染

为方法创建选择器时,应使用Obj C方法签名作为选择器的基础,因为使用Obj C运行时完成了模糊处理。

所以原来的选择器应该是

initWithIdentifier:source:destination:

现在,这有点奇怪,因为定义了init方法,因此第一个参数上的标签是必需的(identifier两次),所以实际上要使用的选择器是

ftg_initWithIdentifier:source:destination:

我能找到的唯一文档是关于从Obj C到Swift的翻译的,但看起来好像是从Swift到Obj C的相反。

接下来,init...是一个实例方法,因此您需要进行两项更改。您需要更改class_getClassMethodclass_getInstanceMethod并且需要classft_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())
}
2020-07-07