【问题标题】:Are method swizzling and isa swizzling the same thing? [closed]method swizzling 和 isa swizzling 是一回事吗? [关闭]
【发布时间】:2016-08-10 15:18:25
【问题描述】:

method swizzling 和 isa swizzling 是一回事吗?如果不是,那么什么是 swizzling?

【问题讨论】:

    标签: objective-c swizzling method-swizzling isa-swizzling


    【解决方案1】:

    方法混搭

    方法调配在运行时交换类的两个方法的实现。这将影响修改后的类的每个已创建或将要创建的实例。

    示例: 假设您已经为 NSString 编写了一个类别:

    @interface NSString (Swizzling)
    @end
    @implementation NSString (Swizzling)
    - (NSString *)swizzled_uppercaseString {
        //when the method is swizzled, the original method will be called 
        //with swizzled_uppercaseString (so this will not create a stack overflow).
        NSString *result = [self swizzled_uppercaseString];
        // our custom code
        result = [result stringByAppendingString:@" (swizzled)"];
        return result;
    }
    @end
    

    然后您可以将uppercaseString-方法的实现与swizzled_uppercaseString-方法交换,这样swizzled_uppercaseString 方法的实现就会在调用uppercaseString 时执行。 (并在调用swizzled_uppercaseString时执行uppercaseString的原始实现):

    #import <objc/runtime.h>
    
    NSString *sample = @"abc";
    
    // original method is called:
    NSLog([sample uppercaseString]); 
    
    //Obtaining original and swizzled method:
    original = class_getInstanceMethod([NSString class], @selector(uppercaseString));
    swizzled = class_getInstanceMethod([NSString class], @selector(swizzled_uppercaseString));
    
    //Exchange implementations here:
    method_exchangeImplementations(original, swizzled);
    
    // swizzled method is called:
    NSLog([sample uppercaseString]); //prints "ABC (swizzled)"
    


    ISA 混搭

    ISA swizzling 修改单个对象的属性,即 ISA ('is a') 属性,它描述对象的类,因此您可以在运行时将给定单个对象的类型与另一种类型交换.

    示例: 假设你有这样的类结构:

    @interface Sample : NSObject
    @property (nonatomic) NSString *sampleStringToLoad;
    @end
    @implementation Sample
    @synthesize sampleStringToLoad;
    @end
    
    @interface SampleWithStringLoader :NSObject
    @property (nonatomic) NSString *sampleStringToLoad;
    -(void)loadString;
    @end
    @implementation SampleWithStringLoader
    @synthesize sampleStringToLoad;
    -(void)loadString {
    self.sampleStringToLoad = @"abc";
    }
    @end
    

    然后您可以将类设置为SampleWithStringLoader,这样sampleStringToLoad-方法就可用了:

    #import <objc/runtime.h>
    
    Sample *sample = [Sample new];
    // switch isa to new class:
    object_setClass(sample, [SampleWithStringLoader class]);
    
    // invoke method that is only in SampleWithStringLoader: 
    [sample performSelector:@selector(loadString)]; 
    
    // switch isa back to original class:
    object_setClass(sample,[Sample class]); 
    
    // Prints 'abc':
    NSLog(sample.sampleStringToLoad);  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-02
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      • 1970-01-01
      相关资源
      最近更新 更多