ios专题征服SwiftiOS杂文

Swift3.x 继续 Method Swizzling

2017-06-05  本文已影响1615人  知忧丶

前言

国外大牛提供了优雅的解决方案

解决思路:initialize()无非就是提供一个入口允许我们将runtime代码插入到适当的位置,那么这个入口是每一个Class必须实现且一定会执行的方法,那么这个就和代理模式很接近了。那么我们可以在程序刚启动时使用runtime获取所有的Class,然后对他们遍历,如果他是Protaocl的代理就立即执行代理方法,我们只需要在代理方法中实现initialize()中要实现的代码。

/// 定义 `protocol`
public protocol SelfAware: class {
    static func awake()
}

// 创建代理执行单例
class NothingToSeeHere{

    static func harmlessFunction(){
        let typeCount = Int(objc_getClassList(nil, 0))
        let  types = UnsafeMutablePointer<AnyClass?>.allocate(capacity: typeCount)
        let autoreleaseintTypes = AutoreleasingUnsafeMutablePointer<AnyClass?>(types)
        objc_getClassList(autoreleaseintTypes, Int32(typeCount)) //获取所有的类
        for index in 0 ..< typeCount{
            (types[index] as? SelfAware.Type)?.awake() //如果该类实现了SelfAware协议,那么调用awake方法
        }
        types.deallocate(capacity: typeCount)
    }
}

/// 执行单例
extension UIApplication {
    private static let runOnce:Void = {
        //使用静态属性以保证只调用一次(该属性是个方法)
        NothingToSeeHere.harmlessFunction()
        UIButton.harmlessFunction()
    }()
    
    open override var next: UIResponder?{
        UIApplication.runOnce
        return super.next
    }
}
/// 将类设置为代理并在代理中实现运行时代吗
extension UIButton:SelfAware{
    public static func awake() {
        let instance = UIButton.appearance()
        instance.setTitleColor(UIColor.red, for: .normal)
        instance.backgroundColor = UIColor.green
        instance.titleLabel?.font = UIFont.boldSystemFont(ofSize: 15)
        
    }

后记&&体悟

虽然Swift弃用了loadinitialize()方法,但我个人认为现阶段影响不是特别大,从Swift角度来看我们要使用runtime的代码大多是和UIKit相关的,而UIKit又是由Objective-C编写的,事实上使用Objective-C来实现是最好的方法,强行使用Swift岂不是缘木求鱼吗?Swift将绝大多数Foundation框架下的许多类改写成了struct,runtime使用的也是比较少的,退一步讲大不了使用Objective-C完成Swift相对难实现的代码,只不过是将Swift代码和Objective-C代码桥接一下,功能同样实现而且省时省工,难道不好吗?

参考链接

上一篇下一篇

猜你喜欢

热点阅读