如何混淆初始化方法?

时间:2018-06-21 15:12:49

标签: objective-c initialization method-swizzling

我有一个带有初始化方法的类MyOldController

    -(instancetype) initWithMyController: (MyController *) myController {
    if((self = [self init])) {
        _myController = myController;
    }
    return self;
}

我想将此初始化方法转换为另一个方法,并将其转换为我的转换代码

@implementation MyOldController(Swizzle)

+ (void)load {
    [MyOldController swizzleMethods];
}

+ (void)swizzleMethods {
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(initWithMyController)), class_getInstanceMethod(self, @selector(swizzle_ initWithMyController)));
}

我尝试写这个

-(instancetype) swizzle_initWithMyController: (MyController *) myController {
    if((self = [self init])) {
        _myController = myController;
    }
    return self;
}

但是它会丢弃错误enter image description here

然后我将init方法重命名为此并更新了(void)swizzleMethods

-(instancetype) initWithMyController_swizzle: (MyController *) myController {
    if((self = [self init])) {
        _myController = myController;
    }
    return self;
}

错误消息消失了,但不起作用。它只是调用旧的初始化方法,而不是我的新方法。

我错过了哪一点?繁琐的初始化方法有一些特殊的方法吗?

1 个答案:

答案 0 :(得分:2)

(从必要的警告开始:这是非常危险的,绝不应该在生产代码中使用。在指定初始化器链接的情况下,初始化初始化器特别危险,绝对不要在没有先确认实现的情况下进行探索和调试以外的任何操作混乱的初始值设定项。好,将其清除。)

我无法复制您的问题。并且初始化程序应始终以init开头,因此第二种方法是正确的。我怀疑您刚刚犯了一个小错误,也许是在您的@selector中(您的问题中有一个错字,这表明您的实际代码中可能有一个错误)。这是执行您所描述内容的代码。

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface MyOldController: NSObject
- (instancetype)initWithInt:(NSInteger)x
@end

@implementation MyOldController
- (instancetype)initWithInt:(NSInteger)x
{
    self = [super init];
    if (self) {
        NSLog(@"init");
    }
    return self;
}
@end

@implementation MyOldController(Swizzle)

+ (void)load {
    [MyOldController swizzleMethods];
}

+ (void)swizzleMethods {
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(initWithInt:)), class_getInstanceMethod(self, @selector(initWithInt_swizzle:)));
}

- (instancetype)initWithInt_swizzle:(NSInteger)x
{
    self = [super init];
    if (self) {
        NSLog(@"init_swizzle");
    }
    return self;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MyOldController *controller = [[MyOldController alloc] initWithInt:1];
        NSLog(@"%@", controller);
    }
    return 0;
}

按预期打印:

2018-06-21 12:23:14.431936-0400 test[30981:401466] init_swizzle
2018-06-21 12:23:14.432172-0400 test[30981:401466] <MyOldController: 0x10051ee10>