首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方法Swizzling

方法Swizzling
EN

Stack Overflow用户
提问于 2013-04-20 11:47:28
回答 1查看 728关注 0票数 1

在尝试对NSString类使用Swizzle isEqualToString:方法时,我遇到了一些奇怪的行为。下面是有问题的代码:

代码语言:javascript
复制
#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,以表明我正确地混合了方法,并且特别是一个NSString对象,这样我就可以排除有关class cluster问题的问题。

当我为上面的代码生成程序集时,我看到的不是普通的objc_msgSend调用,而是类似于l_objc_msgSend_fixup_isEqualToString_的东西。这让我发现了更多关于objective-c vtable的信息,其中似乎可以找到isEqualToString:

代码语言:javascript
复制
static const char * const defaultVtable[] = {
    "allocWithZone:", 
    "alloc", 
    "class", 
    "self", 
    "isKindOfClass:", 
    "respondsToSelector:", 
    "isFlipped", 
    "length", 
    "objectForKey:", 
    "count", 
    "objectAtIndex:", 
    "isEqualToString:", 
    "isEqual:", 
    "retain", 
    "release", 
    "autorelease", 
};

我一整天都在钻研objective-c源码和互联网,想知道怎样才能以某种方式仍然能够和isEqualToString:打交道。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-21 01:58:34

如您所知,这是一个类集群。您需要的是实际的类,而不是公共类,所以只需询问您拥有的string对象:

代码语言:javascript
复制
NSString *foo = @"Foo";

m1 = class_getInstanceMethod([foo class], @selector(isEqualToString:));
m2 = class_getInstanceMethod([foo class], @selector(custom_isEqualToString:));
method_exchangeImplementations(m1, m2);

还有一种脆弱的替代方法,使用类名本身:

代码语言:javascript
复制
NSClassFromString(@"__NSCFConstantString")
NSClassFromString(@"__NSCFString")
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16116348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档