经过从 OC 到 Swift 的过渡, Cocoa 框架中的许多内容也在随着变化, 特别是通知机制的使用方式. 而这里面又牵扯到了 Notification Name 从字符串到一个专门类型(Notification.Name)的转变.
难道很多时候都只有写 Notification.Name("xxx")
这样的代码来生成 Notification 名称?
这样的方式必然带来很多不必要的代码. 其实还可以通过如下的方式来统一管理自定义 Notification.Name.
实现 Notification.Name 对象的统一获取
这里不得不提到 RawRepresentable
协议, 它是一个协议, 如果某个类型实现了它, 就可以将 rawValue
对应转换为对象. enum
默认是实现了 RawRepresentable
协议的.
利用如下代码, 扩展 enum, 为它增加一个 Notification.Name
类型的 name
属性:
protocol INotificationName {
var name: Notification.Name { get }
}
enum GlobalNotificationNames: String, INotificationName {// 这里就是通知名称枚举
case networkUnavailable // 网络不可用
case networkAvailabable // 网络可用
//...
}
extension RawRepresentable where RawValue == String, Self: INotificationName {
var name: Notification.Name {// 在这里就可以将 rawValue 对应转换为想要的对象
return Notification.Name(self.rawValue)
}
}
上面的代码首先定义了一个 INotificationName 接口(协议), 在接口里有一个 name 属性, 通过这个属性就可以获取 Notification.Name 对象.
然后通过扩展 RawRepresentable 协议, 限制 RawValue == String
, 且限制实现 RawRepresentable 协议的类型自身是实现了 INotificationName 接口的.
而后就声明我们的 enum 是实现了 INotificationName 接口(因为 enum 默认就是实现了 RawRepresentable 接口的, 而 INotificationName 的实现就在上面的 extension 中.)
此时就可以直接在 GlobalNotificationNames 里面添加需要的通知名称了. 即上述代码在使用时只需要往 enum 中增加需要的 case 即可, 一个 case 对应一个自定义通知.
如何使用
使用的时候, 直接利用上面定义的 GlobalNotificationNames
的 name
属性获取通知名称对象即可:
let notifName = GlobalNotificationNames.networkUnavailable.name // 获取通知名称对象
NotificationCenter.default.post(name: notifName, object: nil) // 发送通知
//...
// 其他地方观察通知
let notifName = GlobalNotificationNames.networkUnavailable.name // 获取通知名称对象
// 观察通知
NotificationCenter.default.addObserver(self,
selector: #selector(xxxxx),
name: notifName,
object: nil)
想要添加更多的自定义通知, 只需在 enum 中增加 case:
enum GlobalNotificationNames: String, INotificationName {// 这里就是通知名称枚举
case networkUnavailable // 网络不可用
case networkAvailabable // 网络可用
case needSaveOfflineData // 需要保存离线数据(离线缓存已满时)
//...
}
网友评论