我在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
的{{1}}的类别中定义,因此我添加了(NSStringExtensionMethods)
混合以显示我{&#39}。正确地混合方法,特别是成功rangeOfString
个对象,这样我就可以消除有关class cluster个问题的问题。
当我为上面的代码生成程序集时,我没有看到正常的NSString
调用,而是查看objc_msgSend
之类的内容。这让我发现了objective-c vtable的更多信息,其中l_objc_msgSend_fixup_isEqualToString_
似乎可以找到:
isEqualToString:
我整天都在挖掘目标c来源和互联网,以了解如何以某种方式仍然可以调动static const char * const defaultVtable[] = {
"allocWithZone:",
"alloc",
"class",
"self",
"isKindOfClass:",
"respondsToSelector:",
"isFlipped",
"length",
"objectForKey:",
"count",
"objectAtIndex:",
"isEqualToString:",
"isEqual:",
"retain",
"release",
"autorelease",
};
。
答案 0 :(得分:0)
如您所知,这是一个类集群。您需要实际类,而不是公共类,所以只需询问您拥有的字符串对象:
NSString *foo = @"Foo";
m1 = class_getInstanceMethod([foo class], @selector(isEqualToString:));
m2 = class_getInstanceMethod([foo class], @selector(custom_isEqualToString:));
method_exchangeImplementations(m1, m2);
使用类名本身也有一个脆弱的选择:
NSClassFromString(@"__NSCFConstantString")
NSClassFromString(@"__NSCFString")