正如@vikingosegundo 建议的那样,您可以使用方法调配:
#import "ClassA+Test.h"
#import <objc/runtime.h> // Needed for method swizzling
@implementation ClassA(Test)
-(void) swizzled_setImportantProperty:(id) newValue {
[self swizzled_setImportantProperty: newValue]; //it is NOT an endless recursion.
NSLog(@"%@, %@", newValue, [NSThread callStackSymbols]);
}
+(void)load
{
Method original, swizzled;
original = class_getInstanceMethod(self, @selector(setImportantProperty:));
swizzled = class_getInstanceMethod(self, @selector(swizzled_setImportantProperty:)); //UPDATE: missed a column here, sorry!
method_exchangeImplementations(original, swizzled);
}
@end
在这里,我们声明了一个新方法swizzled_setImportantProperty:
,并在运行时将它的实现与setImportantProperty:
实现交换。这样当我们调用setImportantProperty:
代码时,就会调用 for 的实现,swizzled_setImportantProperty
反之亦然。
这就是为什么当我们在实现swizzled_setImportantProperty:
内部调用时swizzled_setImportantProperty:
,它不会调用无限递归,因为setImportantProperty:
会调用实现。正是我们需要的。
更新:由于重写+load
方法可能会导致问题,如果它已经实现(或者如果库创建者将来可能实现),@JoshCaswell 建议了一个更好的选择:
#import "ClassA+Test.h"
#import <objc/runtime.h> // Needed for method swizzling
@implementation ClassA(Test)
-(void) swizzled_setImportantProperty:(id) newValue {
[self swizzled_setImportantProperty: newValue]; //it is NOT an endless recursion.
NSLog(@"%@, %@", newValue, [NSThread callStackSymbols]);
}
@end
void swizzleSetImportantProperty(void) __attribute__((constructor))
{
Method original, swizzled;
original = class_getInstanceMethod([ClassA class], @selector(setImportantProperty:));
swizzled = class_getInstanceMethod([ClassA class], @selector(swizzled_setImportantProperty:)); //UPDATE: missed a column here, sorry!
method_exchangeImplementations(original, swizzled);
}