Я столкнулся с каким-то странным поведением при попытке метода Swizzle isEqualToString:
класса NSString
. Вот код, о котором идет речь:Метод Swizzling isEqualToString
#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
называется (NSStringExtensionMethods)
, поэтому я включил rangeOfString
Swizzle, чтобы показать, что я правильно swizzling методы и специально NSString
объект успешно так Я мог бы устранить вопросы о проблемах class cluster.
Когда я создаю сборку для кода выше, вместо того, чтобы видеть нормальный 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:
.
Дон» t ** когда-либо ** swizzle вещи, которые реализуют шаблон FlyWeight и/или кластер Класса. Это просто пустая трата времени. – CodaFi
Тратить время не всегда пустая трата времени. На данный момент мне в основном просто любопытно –