美文网首页Swift编程
Method-Swizzling on Swift4

Method-Swizzling on Swift4

作者: YYYYYY25 | 来源:发表于2018-07-23 16:41 被阅读16次
一、前言

因为Swift本身对Runtime的支持并不是很到位,尤其是Method-Swizzling在OC中非常常用,但是到Swift后发现load方法不见了进而需要用initialize代替,甚至到了Swift4中直接取消了initialize方法。

这里提供一个Swift3中Method-Swizzling的实现方法:这里

本文提供一个在Swift4中的实现方法,来自于前两天看的一个公开课视频,供大家参考:

二、实现思路

1 声明一个接口并公开的一个方法
2 在AppDelegate中遍历所有类,判断其是否实现了接口中的方法
3 在需要方法交换的类中实现接口,并重写方法

直接上代码:
Awake类的作用是遍历所有注册的类,然后判断其有没有实现LoadProtocol协议,如果有,则调用协议中的awake方法

protocol LoadProtocol {
    static func awake()
}

class Awake {
    fileprivate class func performOnce() {
        /// 注册类的个数
        let count = Int(objc_getClassList(nil, 0))
        /// 分配内存空间
        let classes = UnsafeMutablePointer<AnyClass?>.allocate(capacity: count)
        /// 强转
        let autoreleaseClassed = AutoreleasingUnsafeMutablePointer<AnyClass>(classes)
        /// 获取所有的类
        objc_getClassList(autoreleaseClassed, Int32(count))
        for index in 0..<count {
            (classes[index] as? LoadProtocol.Type)?.awake()
        }
        classes.deallocate()
    }
}

调用在AppDelegate的didFinishLaunchingWithOptions:

Awake.performOnce()

在target中实现LoadProtocol协议中的方法,在awake方法中写方法交换的代码

class ViewController: UIViewController, LoadProtocol {
    class func awake() {
        guard let m1 = class_getInstanceMethod(self, #selector(viewWillAppear(_:))) else {
            return
        }
        guard let m2 = class_getInstanceMethod(self, #selector(swizz_viewWillAppear(_:))) else {
            return
        }
        method_exchangeImplementations(m1, m2);
    }
    @objc dynamic func swizz_viewWillAppear(_ animated:Bool) {
        self.swizz_viewWillAppear(animated)
        print("swizz_viewWillAppear....")
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

完成😁

相关文章

网友评论

    本文标题:Method-Swizzling on Swift4

    本文链接:https://www.haomeiwen.com/subject/xrejmftx.html