背景
- (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。
总结
通过类别拓展属性的办法适用于需要临时增加某些属性的情况,在实现文件中编写类别,这样在依赖该头文件的文件中不会受到干扰。
如果更复杂的情况可以考虑使用组合或继承。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于