Objective-C方法Swizzling示例不起作用

时间:2014-11-21 13:24:50

标签: objective-c method-swizzling

我想尝试使用Method Swizzling清楚地了解它是如何工作的。 看看这段代码:http://nshipster.com/method-swizzling/。 我创建了一个类和一个类别,这里是代码

#import <Foundation/Foundation.h>

@interface CustomClass : NSObject

-(void) originalMethod;

@end

课程的实施

#import "CustomClass.h"

@implementation CustomClass

-(id) init {
    self = [super init];
    return self;
}

-(void) originalMethod {
    NSLog(@"I'm the original method");
}

@end

类别标题:

#import "CustomClass.h"

@interface CustomClass (CustomCategory)

-(void) newMethod;

@end

类别实施

#import "CustomClass+CustomCategory.h"
#include <objc/runtime.h>

@implementation CustomClass (CustomCategory)

-(void) newMethod {
    [self newMethod];
    NSLog(@"I'm the new method");
}

+(void) load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        // When swizzling a class method, use the following:
        // Class class = object_getClass((id)self);

        SEL originalSelector = @selector(originalMethod:);
        SEL swizzledSelector = @selector(newMethod:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod = class_addMethod(class,
                                            originalSelector,
                                            method_getImplementation(swizzledMethod),
                                            method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

@end

这是主要的:

#import <Foundation/Foundation.h>
#import "CustomClass.h"
#import "CustomClass+CustomCategory.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        CustomClass *cc = [[CustomClass alloc] init];
        [cc newMethod];
    }
    return 0;
}

当我打电话给[cc newMethod]时,我得到了无限循环,这根据我链接的文章不应该发生。 我无法在此代码中看到错误。

4 个答案:

答案 0 :(得分:1)

问题在于语法,而不是

SEL originalSelector = @selector(originalMethod:);
SEL swizzledSelector = @selector(newMethod:);

我应该写:

SEL originalSelector = @selector(originalMethod);
SEL swizzledSelector = @selector(newMethod);
xCode只给了我一个警告,所以我没想到选择器名称是错误的。

答案 1 :(得分:0)

    class_replaceMethod(class,
                        swizzledSelector,
                        method_getImplementation(originalMethod),
                        method_getTypeEncoding(originalMethod));

不应method_getImplementation(originalMethod)swizzledMethod

答案 2 :(得分:0)

好像你在调整类方法:

Class class = [self class];

指向+load上下文中的元类,尝试明确指定它,即

Class class = [CustomClass class];
// or
Class class = self;

另外,@ bbum说什么

答案 3 :(得分:0)

  1. 语法错误,运行时会发送不同的消息。

    BOOL didAddMethod =
    class_addMethod(class, originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    
    }
    
  2. 如果第一种方式无效。试试吧:

    File.separator
  3. 交换实施可能会有效。