代码之家  ›  专栏  ›  技术社区  ›  Danil

如何旋转初始化方法?

  •  1
  • Danil  · 技术社区  · 7 年前

    我有一个带init方法的MyOldController类

    —(instanceType)initWithMyController:(MyController*)MyController{
    if((self=[self init])){
    _ mycontroller=mycontroller;
    }
    回归自我;
    }
    

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

    实现myoldcontroller(swizzle) +(空隙)荷载{ [MyOldController冲洗方法]; } +(空)冲洗方法{ 方法ExchangeImplementations(class_GetInstanceMethod(self,@selector(initwithmocontroller)),class_GetInstanceMethod(self,@selector(swizzle_initwithmocroller)); }

    我试着写这个

    —(instancetype)swizzle initwithmycontroller:(mycontroller*)mycontroller{
    if((self=[self init])){
    _ mycontroller=mycontroller;
    }
    回归自我;
    }
    

    但它会减少错误

    然后我将init方法重命名为this并更新(void)swizzlemethods

    —(instanceType)initWithMyController_swizzle:(MyController*)MyController{
    if((self=[self init])){
    _ mycontroller=mycontroller;
    }
    回归自我;
    }
    

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

    我错过了什么?初始化方法的切换是否有一些特殊的方法?

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

    @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方法重命名为this并更新(void)swizzlemethods

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

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

    我错过了什么?初始化方法的切换是否有一些特殊的方法?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Rob Napier    7 年前

    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>