+ (void)initialize { if (self == [MyViewController class]) { // 獲取原始方法和替代方法 Method originalMethod = class_getInstanceMethod([self class], @selector(viewDidLoad)); Method swizzledMethod = class_getInstanceMethod([self class], @selector(xxx_viewDidLoad)); // 執行方法交換 method_exchangeImplementations(originalMethod, swizzledMethod); } } // 新的 viewDidLoad 實現 - (void)xxx_viewDidLoad { // 在原始 viewDidLoad 之前執行你自定義的行為 NSLog(@"viewDidLoad is called"); // 調用原始 viewDidLoad(因為方法交換了,實際上是調用原來的 viewDidLoad) [self xxx_viewDidLoad]; }
OC版本
+ (void)hookClass:(Class)cls originalSelector:(SEL)orlSelector swizzledSelector:(SEL)swzdSelector { Method originalMethod = class_getInstanceMethod(cls, orlSelector); Method swizzledMethod = class_getInstanceMethod(cls, swzdSelector); if (class_addMethod(self, orlSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) { class_replaceMethod(self, swzdSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }
OC版應用實例方法替換 用自己的zf_dealloc 替換系統的dealloc
+ (void)initialize { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ SEL selectors[] = { NSSelectorFromString(@"dealloc") }; for (NSInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) { SEL originalSelector = selectors[index]; SEL swizzledSelector = NSSelectorFromString([@"zf_" stringByAppendingString:NSStringFromSelector(originalSelector)]); Method originalMethod = class_getInstanceMethod(self, originalSelector); Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector); if (class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) { class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } }); } - (void)zf_dealloc { [self.smallFloatView removeFromSuperview]; self.smallFloatView = nil; [self zf_dealloc]; }
Swift版本
// MARK: - 三、Hook @objc public extension NSObject { /// 實例方法替換 static func hookInstanceMethod(of origSel: Selector, with replSel: Selector) -> Bool { let clz: AnyClass = classForCoder() guard let oriMethod = class_getInstanceMethod(clz, origSel) as Method? else { JKPrint("原 實例方法:Swizzling Method(\(origSel)) not found while swizzling class \(NSStringFromClass(classForCoder())).") return false } guard let repMethod = class_getInstanceMethod(clz, replSel) as Method? else { JKPrint("新 實例方法:Swizzling Method(\(replSel)) not found while swizzling class \(NSStringFromClass(classForCoder())).") return false } // 在進行 Swizzling 的時候,需要用 class_addMethod 先進行判斷一下原有類中是否有要替換方法的實現 let didAddMethod: Bool = class_addMethod(clz, origSel, method_getImplementation(repMethod), method_getTypeEncoding(repMethod)) // 如果 class_addMethod 返回 yes,說明當前類中沒有要替換方法的實現,所以需要在父類中查找,這時候就用到 method_getImplemetation 去獲取 class_getInstanceMethod 里面的方法實現,然后再進行 class_replaceMethod 來實現 Swizzing if didAddMethod { class_replaceMethod(clz, replSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod)) } else { method_exchangeImplementations(oriMethod, repMethod) } return true } /// 類方法替換 static func hookClassMethod(of origSel: Selector, with replSel: Selector) -> Bool { let clz: AnyClass = classForCoder() guard let oriMethod = class_getClassMethod(clz, origSel) as Method? else { JKPrint("原 類方法:Swizzling Method(\(origSel)) not found while swizzling class \(NSStringFromClass(classForCoder())).") return false } guard let repMethod = class_getClassMethod(clz, replSel) as Method? else { JKPrint("新 類方法 replSel:Swizzling Method(\(replSel)) not found while swizzling class \(NSStringFromClass(classForCoder())).") return false } // 在進行 Swizzling 的時候,需要用 class_addMethod 先進行判斷一下原有類中是否有要替換方法的實現 let didAddMethod: Bool = class_addMethod(clz, origSel, method_getImplementation(repMethod), method_getTypeEncoding(repMethod)) // 如果 class_addMethod 返回 yes,說明當前類中沒有要替換方法的實現,所以需要在父類中查找,這時候就用到 method_getImplemetation 去獲取 class_getInstanceMethod 里面的方法實現,然后再進行 class_replaceMethod 來實現 Swizzing if didAddMethod { class_replaceMethod(clz, replSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod)) } else { method_exchangeImplementations(oriMethod, repMethod) } return true } /// 方法替換 static func hookMethod(of origSel: Selector, with replSel: Selector, isClassMethod: Bool) -> Bool { let clz: AnyClass = classForCoder() guard let oriMethod = (isClassMethod ? class_getClassMethod(clz, origSel) : class_getClassMethod(clz, origSel)) as Method?, let repMethod = (isClassMethod ? class_getClassMethod(clz, replSel) : class_getClassMethod(clz, replSel)) as Method? else { JKPrint("Swizzling Method(s) not found while swizzling class \(NSStringFromClass(classForCoder())).") return false } // 在進行 Swizzling 的時候,需要用 class_addMethod 先進行判斷一下原有類中是否有要替換方法的實現 let didAddMethod: Bool = class_addMethod(clz, origSel, method_getImplementation(repMethod), method_getTypeEncoding(repMethod)) // 如果 class_addMethod 返回 yes,說明當前類中沒有要替換方法的實現,所以需要在父類中查找,這時候就用到 method_getImplemetation 去獲取 class_getInstanceMethod 里面的方法實現,然后再進行 class_replaceMethod 來實現 Swizzing if didAddMethod { class_replaceMethod(clz, replSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod)) } else { method_exchangeImplementations(oriMethod, repMethod) } return true } }
浙公網安備 33010602011771號