给现有类拓展属性

BB-fat 的个人博客 本文由博客端 https://www.fatech.online 主动推送

背景

- (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 个参数:


接下来是类别的实现部分:

@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。

总结

通过类别拓展属性的办法适用于需要临时增加某些属性的情况,在实现文件中编写类别,这样在依赖该头文件的文件中不会受到干扰。

如果更复杂的情况可以考虑使用组合或继承。

  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    70 引用 • 122 回帖 • 7 关注

赞助商 我要投放

回帖
请输入回帖内容 ...