iOS - Swift 方法交换

作者: GA_ | 来源:发表于2018-07-19 14:49 被阅读22次
    • 想办法在程序启动的时候执行一次方法交换
    • 方法1需要每个类都添加一个方法 然后调用
    • 方法2将所有遵守协议SwizzleProtocol的类遍历 调用协议方法
      // 001
    extension ViewController {
        static func yy_swizzle() {
            guard let m1 = class_getInstanceMethod(self, #selector(viewWillAppear(_:))) else {
                return
            }
            guard let m2 = class_getInstanceMethod(self, #selector(swizzle_viewWillAppear(_:))) else {
                return
            }
            
            if (class_addMethod(self, #selector(swizzle_viewWillAppear(_:)), method_getImplementation(m2), method_getTypeEncoding(m2))) {
                class_replaceMethod(self, #selector(swizzle_viewWillAppear(_:)), method_getImplementation(m1), method_getTypeEncoding(m1))
            } else {
                method_exchangeImplementations(m1, m2)
            }
        }
        
        @objc func swizzle_viewWillAppear(_ animated: Bool) {
            swizzle_viewWillAppear(animated)
            print("swizzle_viewWillAppear")
        }
    }
    
    /*
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        ViewController.yy_swizzle()
     return true
     }
     */
    

    // 002

    extension ViewController: SwizzleProtocol {
    
        static func swizzle() {
            guard let m1 = class_getInstanceMethod(self, #selector(viewWillAppear(_:))) else {
                return
            }
            guard let m2 = class_getInstanceMethod(self, #selector(yy_viewWillAppear(_:))) else {
                return
            }
            
            if (class_addMethod(self, #selector(yy_viewWillAppear(_:)), method_getImplementation(m2), method_getTypeEncoding(m2))) {
                class_replaceMethod(self, #selector(yy_viewWillAppear(_:)), method_getImplementation(m1), method_getTypeEncoding(m1))
            } else {
                    method_exchangeImplementations(m1, m2)
            }
        }
        
        @objc func yy_viewWillAppear(_ animated: Bool) {
            yy_viewWillAppear(animated)
            print("yy_viewWillAppear")
        }
    }
    
    
    protocol SwizzleProtocol {
        static func swizzle()
    }
    
    class Swizzle {
        // 获取到所有的类,遍历类,遵守协议AwakeProtocol的类执行awake方法
        static func performOnce() {
            let count = Int(objc_getClassList(nil, 0))
            let classes = UnsafeMutablePointer<AnyClass?>.allocate(capacity: count)
            let autoreleaseClasses = AutoreleasingUnsafeMutablePointer<AnyClass>(classes)
            objc_getClassList(autoreleaseClasses, Int32(count))
            for index in 0..<count {
                (classes[index] as? SwizzleProtocol.Type)?.swizzle()
            }
            classes.deallocate()
        }
    }
    
    /*
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        Swizzle.performOnce()
        return true
     }
     */
    

    相关文章

      网友评论

      • Rdxer:方法2 其实不怎么好, 替换 父类方法 子类 也会 进行一次替换操纵,

      本文标题:iOS - Swift 方法交换

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