一、前言
因为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.
}
}
完成😁
网友评论