1. 程式人生 > >筆記:利用 runtime 交換方法、給分類動態新增屬性

筆記:利用 runtime 交換方法、給分類動態新增屬性

第一次寫部落格,有些小緊張,如有不對的地方還請大牛們及時指出,在此先感謝各位大牛了...


一、利用 runtime 交換方法:

1、交換方法的實現

#import "UIImage+mImage.h"

@implementation UIImage (mImage)
+(void)load{
    //load 把類載入到記憶體時呼叫,只會呼叫一次,在這裡用 runtime 交換方法,能夠確保在呼叫方法之前交換。
    //1、 獲取方法的地址 class_getClassMethod(引數1->類,引數2->方法名) (獲取 'get' 某個類 ‘class' 的方法 ’method‘
    Method imageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
    Method in_imageNamedMethod = class_getClassMethod(self, @selector(in_imageNamed:));
    
    //2、交換方法的地址,相當於交換實現方式 method_exchangeImplementations(引數1->方法地址1,引數2->方法地址2) (方法 ’method‘ 交換 ’exchange‘ 實現方式 ’Implementations‘)
    method_exchangeImplementations(imageNamedMethod, in_imageNamedMethod);
    
    
}

// 呼叫 imageNamed => in_imageNamed
// 呼叫 in_imageNamed => imageNamed
+(UIImage *)in_imageNamed:(NSString *)name{
    UIImage *image = [UIImage in_imageNamed:name];
    if (image) {
        NSLog(@"runtime交換方法--載入成功");
    }else{
        NSLog(@"runtime交換方法--載入失敗");
    }
    return image;
}
@end

2、呼叫

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *iamgeV;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UIImage *image = [UIImage imageNamed:@"XXX"];
    _iamgeV.image = image;
   
}
3、列印
2018-03-16 12:47:43.131559+0800 2[2475:2056911] runtime交換方法--載入成功


二、給分類動態新增屬性:給分類動態新增屬性實質上就是將這個屬性跟這個類關聯起來,例如給 NSObject 新增一個分類,在分類裡給 NSObject 新增一個 title 的屬性,實質上就是將 title 屬性跟 NSObject 類關聯起來。

1、動態新增屬性

#import "NSObject+Title.h"
#import <objc/message.h>
@implementation NSObject (Title)
// 在分類裡是不能給類新增屬性的,即使是用了 @property 也只是生成了 set 和 get 方法的宣告,並沒有生成帶下滑線的屬性以及 set、get 方法的實現。runtime 可以通過 objc_setAssociatedObject(id object->要關聯的物件, const void *key->關聯的屬性名稱, id value->關聯的屬性值, objc_AssociationPolicy policy->儲存策略)方法將屬性跟類關聯起來。(設定 ‘set’ 關聯 ‘associatded' 到類 ’object‘)
-(void)setTitle:(NSString *)title{
    // objc_setAssociatedObject
    objc_setAssociatedObject(self, @"title", title, OBJC_ASSOCIATION_COPY);
    
}
-(NSString *)title{
    // objc_getAssociatedObject
    return objc_getAssociatedObject(self, @"title");
}
@end


2、呼叫驗證

#import "ViewController.h"
#import "NSObject+Title.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   // 呼叫
    NSObject *objc = [[NSObject alloc] init];
    objc.title = @"這是 runtime 動態關聯的屬性";
    NSLog(@"runtime 動態關聯屬性成功,title = %@", objc.title);
}

3、列印

2018-03-16 14:55:20.751379+0800 2[2515:2098412] runtime 動態關聯屬性成功,title = 這是 runtime 動態關聯的屬性


注:本文參考了《iOS模式詳解runtime面試工作》,用自己比較能夠理解的方式做了一下筆記,在此感謝原文作者!