Swift Swizzle Method

752 阅读1分钟

Swift Swizzle Method

如何在swift中实现方法混淆呢:

func swizzleMethod(_ cls: AnyClass, origin: Selector, swizzled: Selector) {
   guard let originMethod = class_getInstanceMethod(cls, origin),
    let swizzledMethod = class_getInstanceMethod(cls, swizzled) else {
        return
    }

    let didAddMethod = class_addMethod(cls, origin, method_getImplementation(originMethod), method_getTypeEncoding(originMethod))
    if didAddMethod {
      class_replaceMethod(cls, swizzled, method_getImplementation(originMethod), method_getTypeEncoding(originMethod))
    } else {
      method_exchangeImplementations(originMethod, swizzledMethod)
    }
}

然后在执行的时候,需要同步的执行,因此需要一个dispatch_once,但是在swift中并没有提供这个方法,因此,自己实现:

extension DispatchQueue {
    private static var _onceTracker = [String]()

    class func once(token: String, block: @escaping () -> Void) {
      objc_sync_enter(self)
      defer {
        objc_sync_exit(self)
      }

      if _onceTracker.contains(token) {
          return
      }
      _onceTracker.append(token)
      block()
    }
}

然后我们在hook的时候,就可以着么做:

DispatchQueue.once(token: "com.dyl.vc") {
  swizzleMethod(UIViewController.self, origin: #selector(UIViewController.present(_:animated:completion:)), swizzled: #selector(UIViewController.swizzledPresent(_:animated:completion:)))
}