クラスでMethod Swizzle を実行しようとすると、奇妙な動作が発生しisEqualToString:
ます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:
とは両方ともcalledrangeOfString:
のカテゴリで定義されているため、メソッドを正しく、特にオブジェクトを正常にスウィズルしていることを示すためにスウィズルを含めて、クラス クラスターの問題に関する疑問を解消できるようにしました。NSString
(NSStringExtensionMethods)
rangeOfString
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",
};
私はどうにかしてまだ swizzle できるようにする方法について、objective-c のソースとインターネットを一日中掘り下げてきましたisEqualToString:
。