Objective-C 方法滑动示例不起作用



我想尝试使用方法刷卡来清楚地了解它是如何工作的。查看此代码: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]时,我得到和无限循环,根据我链接的文章,这不应该发生。我看不到此代码中的错误。

问题出在语法上,而不是

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

我应该写:

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

xCode只给了我一个警告,所以我不认为选择器的名字是错误的。

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

method_getImplementation(originalMethod)不应该swizzledMethod吗?

好像你刷卡类方法:

Class class = [self class];

指向上下文+load元类,尝试显式指定它,即

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

另外,@bbum说了什么

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

    SEL originalSelector = @selector(originalMethod);
    SEL swizzledSelector = @selector(newMethod);
    
  2. 如果第一种方法没有效果。试试吧:

    BOOL didAddMethod =
    class_addMethod(class, originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    

交换实现可能会生效。

相关内容

  • 没有找到相关文章

最新更新