通过runtime让属性在category上飞

现在面临的场景

在做项目过程中难免会创建很多ViewModel,这些ViewModel难免有些共同的方法跟属性,这些共同的方法和属性可以单独提取出来,这就用到category.我现在的具体场景是:每个ViewModel都需要请求数据,当ViewController从当前界面切换到另一个画面时,暂停本页面的网络请求.

源码

NSObject+ViewModel.h文件

@interface NSObject (ViewModel)
@property (nonatomic) NSURLSessionDataTask *dataTask;
- (void)cancelTask; //取消任务
- (void)suspendTask; //暂停任务
- (void)resumeTask; //继续任务
@end

NSObject+ViewModel.m文件

#import "NSObject+ViewModel.h"
#import <objc/runtime.h>//得引入runtime

static const void *dataTaskKey = &dataTaskKey;  
@implementation NSObject (ViewModel)

//通过运行时, 实现setter方法动态的绑定属性到对象
/**
  参数一 源对象,此处是self
  参数二 唯一静态变量,dataTaskKey保存的是他自己的地址,因为是静态的,所以地址不会重复
  参数三 关联的对象
  参数四 关联策略(属性的内存管理方式),关联策略详细解释在下面
**/
- (void)setDataTask:(NSURLSessionDataTask *)dataTask{
    objc_setAssociatedObject(self, dataTaskKey, dataTask, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

/**
  参数一 源对象,此处是self
  参数二 唯一静态变量,dataTaskKey保存的是他自己的地址,因为是静态的,所以地址不会重复
**/
- (NSURLSessionDataTask *)dataTask{
    return objc_getAssociatedObject(self, dataTaskKey);
}

- (void)resumeTask{
    [self.dataTask resume];
}
- (void)cancelTask{
    [self.dataTask cancel];
}
- (void)suspendTask{
    [self.dataTask suspend];
}
@end
关联策略
Behavior @property Equivalent Description
OBJC_ASSOCIATION_ASSIGN @property (assign) 或 @property (unsafe_unretained) 指定一个关联对象的弱引用。
OBJC_ASSOCIATION_RETAIN_NONATOMIC @property (nonatomic, strong) 指定一个关联对象的强引用,不能被原子化使用。
OBJC_ASSOCIATION_COPY_NONATOMIC @property (nonatomic, copy) 指定一个关联对象的copy引用,不能被原子化使用。
OBJC_ASSOCIATION_RETAIN @property (atomic, strong) 指定一个关联对象的强引用,能被原子化使用。
OBJC_ASSOCIATION_COPY @property (atomic, copy) 指定一个关联对象的copy引用,能被原子化使用。

这两个方法可以让一个对象和另一个对象关联,就是说一个对象可以保持对另一个对象的引用,并获取那个对象。有了这些,就能实现属性功能了。

END