【问题标题】:Objective-C Method Swizzling example not workingObjective-C Method Swizzling 示例不起作用
【发布时间】:2014-11-21 13:24:50
【问题描述】:

我想尝试 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] 时,我得到了无限循环,根据我链接的文章,这不应该发生。 我在这段代码中看不到错误。

【问题讨论】:

  • 你确定调用的是load方法吗?
  • @user1963877 不,我没有检查过。应该调用它,因为它是 NSObject 中存在的方法。
  • 这里有一些关于使用+(void)loadlink的内容。请注意,您的教程涉及普通的 CocoaTouch 应用程序(带有 ui 线程等),而您在基本上是裸露的 hello world 程序上尝试它,所以它的行为可能不同。
  • @user1963877 不会有所作为。
  • 我知道你发现了问题,但还有一件事:这本身并没有错,但你是从main() 调用[cc newMethod]。当您混合方法时,通常的意图是新方法是隐藏的实现细节。客户将使用旧方法,而 swizzling 的目的是改变其行为。我知道您可能只是在尝试,但想确保您了解它应该如何工作。

标签: objective-c method-swizzling


【解决方案1】:

问题出在语法上,而不是

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

我应该写:

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

xCode 只给了我一个警告,所以我认为选择器名称没有错。

【讨论】:

    【解决方案2】:
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    

    method_getImplementation(originalMethod) 不应该是swizzledMethod吗?

    【讨论】:

      【解决方案3】:

      你好像在混用类方法:

      Class class = [self class];
      

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

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

      另外,@bbum 说了什么

      【讨论】:

        【解决方案4】:
        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);
          
          }
          

        交换实施可能产生的影响。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-03
          • 2020-12-13
          相关资源
          最近更新 更多