我们都知道默认情况下, 因分类底层结构的限制, 是不能添加成员变量到分类中. 但可以利用runtime 关联对象来间接实现.
下面我们来写一个分类, 关联一个属性, 及使用. 其实说到底, 关联一个属性就是为了方便调用.
给AppDelegate写一个分类, 目的是监听 AppDelegate 在前台还是后台.
#import "AppDelegate.h"
#import <objc/runtime.h>
@interfaceAppDelegate (Push)
/// 生成setter/getter 声明
@property(nonatomic,strong) NSNumber* applicationInBackground;
@end
@implementation AppDelegate (Push)
// 利用runtime 交换方法
+ (void)load {
Method original =class_getInstanceMethod(self,@selector(application:didFinishLaunchingWithOptions:));
Method swizzled =class_getInstanceMethod(self,@selector(application:swizzledDidFinishLaunchingWithOptions:));
method_exchangeImplementations(original, swizzled);
}
///实现set 方法
// 参数1: 要给谁关联对象
// 参数2: 储存值对应的key ,因为它底层也key-value 的形式存值的. 这里说一下这个key, 因为get时是根据key get value. 所以比较好的做法可以把 @selector(applicationInBackground) 储存地址当key
// 参数3: 储存值
// 参数4: 相当于property中的类型, 对象类型Strong , 基本类型用 assign, 注意里面的宏.
//objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
- (void)setApplicationInBackground:(NSNumber *)applicationInBackground {
objc_setAssociatedObject(self, @selector(applicationInBackground), applicationInBackground, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/// 实现get 方法
- (NSNumber*)applicationInBackground {
/// 注意保持key 相同
return objc_getAssociatedObject(self,@selector(applicationInBackground));
}
- (BOOL)application:(UIApplication*)application swizzledDidFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
// 调用原始的方法
[self application:application swizzledDidFinishLaunchingWithOptions:launchOptions];
// 给属性赋值
self.applicationInBackground = @(YES);
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication*)application {
self.applicationInBackground = @(NO);
}
- (void)applicationDidEnterBackground:(UIApplication*)application {
self.applicationInBackground = @(YES);
}
// 赋张类型修饰选择图
1.png
到此, 外界只要导入它, 根据 applicationInBackground 就可以知道是在前台还是在后台.
这就是给分类关联一个属性的简便使用.
网友评论