isEqualToString:
在课堂上尝试 Method Swizzle 时,我遇到了一些奇怪的行为NSString
。这是有问题的代码:
#import <Foundation/Foundation.h>
#import <objc/objc-runtime.h>
@interface NSString (SwizzleString)
- (BOOL) custom_isEqualToString:(NSString *)aString;
- (NSRange)custom_rangeOfString:(NSString *)aString;
@end
@implementation NSString (SwizzleString)
- (BOOL) custom_isEqualToString:(NSString *)aString;
{
NSLog(@"Inside custom_isEqualToString method definition");
return [self custom_isEqualToString:aString];
}
- (NSRange)custom_rangeOfString:(NSString *)aString;
{
NSLog(@"Inside custom_rangeOfString method definition");
return [self custom_rangeOfString:aString];
}
@end
int main(int argc, const char * argv[])
{
Method m1, m2;
m1 = class_getInstanceMethod([NSString class], @selector(isEqualToString:));
m2 = class_getInstanceMethod([NSString class], @selector(custom_isEqualToString:));
method_exchangeImplementations(m1, m2);
m1 = class_getInstanceMethod([NSString class], @selector(rangeOfString:));
m2 = class_getInstanceMethod([NSString class], @selector(custom_rangeOfString:));
method_exchangeImplementations(m1, m2);
NSString *foo = @"Foo";
// Does not log anything, is still using isEqualToString: implementation
[foo isEqualToString:@"Foo"];
// Also does not log anything, since it is using the method implementation from isEqualToString:
[foo custom_isEqualToString:@"Foo"];
// Does log something because rangeOfString now uses custom_rangeOfString IMP
[foo rangeOfString:@"Foo"];
// Does not log anything because it uses the method implementation from rangeOfString:
[foo custom_rangeOfString:@"Foo"];
}
isEqualToString:
并且rangeOfString:
都在NSString
called类别中定义(NSStringExtensionMethods)
,因此我包含了rangeOfString
swizzle 以表明我正在正确地调配方法,特别是NSString
成功地调配了一个对象,因此我可以消除有关类集群问题的问题。
当我为上面的代码生成程序集时,我没有看到正常的objc_msgSend
调用,而是看到了类似l_objc_msgSend_fixup_isEqualToString_
. 这让我找到了更多关于objective-c vtable的信息,似乎isEqualToString:
可以在其中找到:
static const char * const defaultVtable[] = {
"allocWithZone:",
"alloc",
"class",
"self",
"isKindOfClass:",
"respondsToSelector:",
"isFlipped",
"length",
"objectForKey:",
"count",
"objectAtIndex:",
"isEqualToString:",
"isEqual:",
"retain",
"release",
"autorelease",
};
我整天都在挖掘objective-c 源代码和互联网,以了解如何以某种方式仍然能够 swizzle isEqualToString:
。