背景
- (void)pushSimpleLocalNotificationWithTitle:(NSString *)title content:(NSString *)content soundName:(NSString *_Nullable)soundName callback:(dispatch_block_t)callback;
该方法的功能是做一次本地推送,点击该推送可以执行一个 block,为了防止用户在 App 内做的某些操作和该 block 冲突,就简单粗暴地在 App 进入前台之后取消掉所有通过这个方法发出的推送。
由于业务还有许多其他发推送的情况,发出的推送统一放在一个 NSMutableDictionary
中,为了区分,希望给 UILocalNotification
增加一个布尔属性 autoRemove
用来标识进入前台是否需要取消,以下是发推送的部分代码:
UILocalNotification *noti = [[UILocalNotification alloc] init]; noti.alertTitle = item.title; noti.alertBody = item.body; noti.category = item.category; noti.soundName = item.soundName; noti.userInfo = item.userInfo; noti.autoRemove = YES; [self.items qh_setObject:noti forKey:itemId]; [[UIApplication sharedApplication] presentLocalNotificationNow:noti];
其中 items
就是存放所有通知的 Dictionary。
解决这个问题有多种不同的办法,这里选择在该 NotificationManager
中给 UILocalNotification
增加一个类别,在这个类别中实现 autoRemove
属性。
实现
首先声明类别的接口:
@interface UILocalNotification (XWNotificationManager) @property(nonatomic, assign) BOOL autoRemove; @end
类别是 OC runtime 的一种特性,所以没有空间给这个类增加一个属性,也就是说上面的这行代码
@property(nonatomic, assign) BOOL autoRemove;
编译器不会自动生成实现。
那么我们就需要手动实现 - (BOOL)autoRemove
和 - (void)setAutoRemove:(BOOL)autoRemove
方法。
这里需要用到 objc_setAssociatedObject 函数:
/** * Sets an associated value for a given object using a given key and association policy. * * @param object The source object for the association. * @param key The key for the association. * @param value The value to associate with the key key for object. Pass nil to clear an existing association. * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.” * * @see objc_setAssociatedObject * @see objc_removeAssociatedObjects */ OBJC_EXPORT void objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
它的功能就是将一个对象和另一个对象关联起来,并且可以通过 objc_getAssociatedObject
函数获取这种关联关系。
下面来分别解释一下这 4 个参数:
-
object:建立关联关系的对象,本例中是
self
-
key:一个唯一的指针
-
value:被关联的对象
-
policy:两者之间的关系
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) { OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */ OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. * The association is not made atomically. */ OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied. * The association is not made atomically. */ OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object. * The association is made atomically. */ OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied. * The association is made atomically. */ };
接下来是类别的实现部分:
@implementation UILocalNotification (XWNotificationManager) static const char UILocalNotificationAssociatedKey; - (BOOL)autoRemove { NSNumber *value = objc_getAssociatedObject(self, &UILocalNotificationAssociatedKey); return value.boolValue; } - (void)setAutoRemove:(BOOL)autoRemove { objc_setAssociatedObject(self, &UILocalNotificationAssociatedKey, [[NSNumber alloc] initWithBool:autoRemove], OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end
key 要求不变,直接用一个静态变量就好。
被关联的必须是指针类型,所以本例中使用 NSNumber
包裹一下 BOOL。
总结
通过类别拓展属性的办法适用于需要临时增加某些属性的情况,在实现文件中编写类别,这样在依赖该头文件的文件中不会受到干扰。
如果更复杂的情况可以考虑使用组合或继承。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于