如何为指定实例调配方法?
How to swizzling method for a designative instance?
class Person
:
@implementation Person
- (void)sayHi {
NSLog(@"hi");
}
- (void)sayHello {
NSLog(@"hello");
}
- (void)swizzlingMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL HI_SEL = @selector(sayHi);
SEL HELLO_SEL = @selector(sayHello);
Method HI_METHOD = class_getInstanceMethod(self.class, HI_SEL);
Method HELLO_METHOD = class_getInstanceMethod(self.class, HELLO_SEL);
BOOL addSuccess = class_addMethod(self.class, HI_SEL, method_getImplementation(HELLO_METHOD), method_getTypeEncoding(HELLO_METHOD));
if (addSuccess) {
class_replaceMethod(self.class, HI_SEL, method_getImplementation(HELLO_METHOD), method_getTypeEncoding(HELLO_METHOD));
} else {
method_exchangeImplementations(HI_METHOD, HELLO_METHOD);
}
});
}
@end
Person的实例调用swizzlingMethod
时,方法sayHi
和方法sayHello
会互换
然而,一旦实例调用swizzlingMethod
,实例的所有方法将被交换:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
Person *person1 = [Person new];
[person1 swizzlingMethod];
[person1 sayHi];
Person *person2 = [Person new];
[person2 sayHi];
}
控制台打印了 hello
和 hello
,即使 person2 没有调用 swizzlingMethod
。
我想要的只是person1的方法exchanged.So有什么方法可以帮助实现吗?
在 Xcode 10.2.1 中,您可以将 swizzlingMethod
声明为 class 方法并像 [Person swizzlingMethod]
一样调用它,而无需更改实现。这意味着此方法为 Person
的所有实例交换 sayHi
和 sayHello
的实现。您不能为特定对象执行此操作,请参阅 this answer 了解更多详细信息。
另外,你有逻辑错误,把class_replaceMethod(self.class, HI_SEL, method_getImplementation(HELLO_METHOD), method_getTypeEncoding(HELLO_METHOD));
换成class_replaceMethod(self.class, HELLO_SEL, method_getImplementation(HI_METHOD), method_getTypeEncoding(HI_METHOD));
。
class Person
:
@implementation Person
- (void)sayHi {
NSLog(@"hi");
}
- (void)sayHello {
NSLog(@"hello");
}
- (void)swizzlingMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL HI_SEL = @selector(sayHi);
SEL HELLO_SEL = @selector(sayHello);
Method HI_METHOD = class_getInstanceMethod(self.class, HI_SEL);
Method HELLO_METHOD = class_getInstanceMethod(self.class, HELLO_SEL);
BOOL addSuccess = class_addMethod(self.class, HI_SEL, method_getImplementation(HELLO_METHOD), method_getTypeEncoding(HELLO_METHOD));
if (addSuccess) {
class_replaceMethod(self.class, HI_SEL, method_getImplementation(HELLO_METHOD), method_getTypeEncoding(HELLO_METHOD));
} else {
method_exchangeImplementations(HI_METHOD, HELLO_METHOD);
}
});
}
@end
Person的实例调用swizzlingMethod
时,方法sayHi
和方法sayHello
会互换
然而,一旦实例调用swizzlingMethod
,实例的所有方法将被交换:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
Person *person1 = [Person new];
[person1 swizzlingMethod];
[person1 sayHi];
Person *person2 = [Person new];
[person2 sayHi];
}
控制台打印了 hello
和 hello
,即使 person2 没有调用 swizzlingMethod
。
我想要的只是person1的方法exchanged.So有什么方法可以帮助实现吗?
在 Xcode 10.2.1 中,您可以将 swizzlingMethod
声明为 class 方法并像 [Person swizzlingMethod]
一样调用它,而无需更改实现。这意味着此方法为 Person
的所有实例交换 sayHi
和 sayHello
的实现。您不能为特定对象执行此操作,请参阅 this answer 了解更多详细信息。
另外,你有逻辑错误,把class_replaceMethod(self.class, HI_SEL, method_getImplementation(HELLO_METHOD), method_getTypeEncoding(HELLO_METHOD));
换成class_replaceMethod(self.class, HELLO_SEL, method_getImplementation(HI_METHOD), method_getTypeEncoding(HI_METHOD));
。