import Foundation
extension DispatchQueue {
private static var _onceTracker = [String]()
public class func once(token: String, block: () -> ()) {
objc_sync_enter(self)
defer {
objc_sync_exit(self)
}
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
func async(block: @escaping ()->()) {
self.async(execute: block)
}
func after(time: DispatchTime, block: @escaping ()->()) {
self.asyncAfter(deadline: time, execute: block)
}
}
import UIKit
private let onceToken = "Method Swizzling viewWillAppear"
extension UIViewController {
public class func initializeMethod() {
// Make sure This isn't a subclass of UIViewController, So that It applies to all UIViewController childs
if self != UIViewController.self {
return
}
//DispatchQueue函数保证代码只被执行一次,防止又被交换回去导致得不到想要的效果
DispatchQueue.once(token: onceToken) {
let originalSelector = #selector(UIViewController.viewWillAppear(_:))
let swizzledSelector = #selector(UIViewController.swizzled_viewWillAppear(animated:))
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
//在进行 Swizzling 的时候,需要用 class_addMethod 先进行判断一下原有类中是否有要替换方法的实现
let didAddMethod: Bool = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
//如果 class_addMethod 返回 yes,说明当前类中没有要替换方法的实现,所以需要在父类中查找,这时候就用到 method_getImplemetation 去获取 class_getInstanceMethod 里面的方法实现,然后再进行 class_replaceMethod 来实现 Swizzing
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
} else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
}
@objc func swizzled_viewWillAppear(animated: Bool) {
//需要注入的代码写在此处
view.backgroundColor = UIColor.red
self.swizzled_viewWillAppear(animated: animated)
}
}
import UIKit
private let onceToken1 = "UITextField.swizzling_draw"
extension UITextField {
@objc func swizzling_draw(_ rect: CGRect) {
setValue(UIFont.systemFont(ofSize: 5, weight: UIFont.Weight.thin), forKeyPath: "_placeholderLabel.font")
swizzling_draw(rect)
}
public class func drawMethod() {
if self != UITextField.self {
return
}
//DispatchQueue函数保证代码只被执行一次,防止又被交换回去导致得不到想要的效果
DispatchQueue.once(token: onceToken1) {
let originalSelector = #selector(UITextField.draw(_:))
let swizzledSelector = #selector(UITextField.swizzling_draw(_:))
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
//在进行 Swizzling 的时候,需要用 class_addMethod 先进行判断一下原有类中是否有要替换方法的实现
let didAddMethod: Bool = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
//如果 class_addMethod 返回 yes,说明当前类中没有要替换方法的实现,所以需要在父类中查找,这时候就用到 method_getImplemetation 去获取 class_getInstanceMethod 里面的方法实现,然后再进行 class_replaceMethod 来实现 Swizzing
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
} else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UITextField.drawMethod()
UIViewController.initializeMethod()
return true
}
--EOF--
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于