前言
在闲来无事的时候,我会抽时间看看Foundation、UIKit等相关库的Swift代码说明与注释。说实话,有的时候看起来真的很乏味,也不容易理解。
不过有的时候也会觉得Apple这么设计API真是书写的简单漂亮,一脸佩服,今天给大家分享的就是从NSNotification.Name学习一种代码编写方式,并且已经在我自己的项目中进行类似这种写法的落地实战分享。
OC时代的通知名写法
NSNotification
想必大家都使用过,在iOS中处理跨非相邻页面、一对多的数据处理的时候,我们通常就是通过发通知传参,告之相关页面处理逻辑。
一般情况下,如果可以避免NSNotification
的时候,我都会尽量避免使用,当然,既然系统给你了这个方法,那么在合适的场景使用也会妙手生花。
当然,对于NSNotification
的通知名的管理,其实是一个看似简单,实际上可以做得非常优雅的事情。
特别是从OC过渡到Swift的过程,这段简单的代码,其实进行了很大的演变,我们不妨来看看。
下面这个是我早期写OC代码的时候,发送一个通知:
[[NSNotificationCenter defaultCenter] postNotificationName:@"CancelActivateSuccessNotification" object:nil];
大家注意看,通知名,我就是非常简单的使用硬编码字符串@"CancelActivateSuccessNotification"
来表示,硬编码的缺点就不用我多说了,编译器是不会给提示的,写错了,甚至连通知事件都没法收到,总之,这种写法是不好的。
于是,看看系统代码以及AFNetworking,我们会看见这样一种写法:
系统通知名:
UIKIT_EXTERN NSNotificationName const UIApplicationDidFinishLaunchingNotification;
AFNetworking的通知名,也是学习系统通知名的写法进行的扩展:
.h文件
.m文件
看起来并不是太高明?也许确实如此,只不过通过.h与.m的分隔,将一个硬编码字符串变成了一个全局可以引用、IDE可以快速键入的方式,但是它至少让调用变得简单与安全,这样就足够了。
于是乎,OC时代通知名的写法,我们基本上都会用以上这种方式进行编写:
.h
UIKIT_EXTERN NSString *const CancelActivateSuccessNotification;
.m
NSString *const CancelActivateSuccessNotification = @"CancelActivateSuccessNotification";
Swift时代还是这么写吗?
Swift时代的通知名写法
其实Swift的早期,基本上还是沿用着OC的这一套写法来写通知名,不过在Swift4.2之后就迎来比较大的改变,让我们来看看调用的API与源码:
open func post(name aName: NSNotification.Name, object anObject: Any?)
open func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil)
发通知的时候,通知名被一个NSNotification.Name
类型代替了,我们进去追着NSNotification.Name
看:
大家一定要记住这种编码的书写方式,先送上结论:
- 可以在一个类型里面再定义一个类型,大家可以自己尝试。
- 什么时候嵌套?为何要这么写?当嵌套的类型与外层定义的类型有着较强关联的时候可以这么写。
说完了这些,我们可以看到在Swift中,发通知,通知名不再是一个字符串了,而是一个NSNotification.Name
类型了。
那么在开发过程中,我们如何使用呢?我们不妨还是从系统提供的API开始找:
因为Swift可以随处编写一个类的分类,于是在一个类的分类中定义好该类的通知名这种书写方式随处可见,这样的好处就是通知名与类紧紧联系在一起,一来便于查找,二来便于绑定业务类型。
NotificationCenter.default.post(name: UIApplication.didFinishLaunchingNotification, object: nil)
上面这个通知一发出,通过通知名我就知道是涉及UIApplication
的操作行为。
说完了系统提供的API,我们再来看看一些知名第三方库是怎么定义吧,这里以Alamofire
为例:
Alamofire
保持了和系统API一样的风格来定义通知名。
我们再来看看Kingfisher
:
Kingfisher
是在NSNotification.Name
分类中扩展了通知名。
顺带说一下,我自己管理与编写通知名是这样的:
extension Notification.Name {
enum LoginService {
/// 退出
static let logoutNotification = NSNotification.Name("logoutNotification")
}
}
NotificationCenter.default.post(name: .LoginService.logoutNotification, object: nil)
通过在NSNotification.Name
分类中进行二级业务扩展,细化通知名。
至于大家更喜欢哪一种写法,那就是仁者见仁智者见智的事情了。
总结
本篇文章从NotificationCenter
发通知的通知名开始,对OC到Swift的写法演进进行梳理与说明,举了系统API和著名第三方库的例子,给大家讲解如何写好并管理好NSNotification.Name
。
吐槽
掘金的这个编辑器,我直接从Xcode里面复制粘贴代码的体验真的很不友好,导致我比较长的代码都是截图,只有较少的代码使用的代码块。
自己写的项目,欢迎大家star⭐️
RxStudy:RxSwift/RxCocoa框架,MVVM模式编写wanandroid客户端。
GetXStudy:使用GetX,重构了Flutter wanandroid客户端。