iOS:NSNotification.Name从OC到Swift的写法演进

前言

在闲来无事的时候,我会抽时间看看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文件

image.png

.m文件
image.png

看起来并不是太高明?也许确实如此,只不过通过.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看:

image.png

大家一定要记住这种编码的书写方式,先送上结论:

  • 可以在一个类型里面再定义一个类型,大家可以自己尝试。
  • 什么时候嵌套?为何要这么写?当嵌套的类型与外层定义的类型有着较强关联的时候可以这么写。

说完了这些,我们可以看到在Swift中,发通知,通知名不再是一个字符串了,而是一个NSNotification.Name类型了。

那么在开发过程中,我们如何使用呢?我们不妨还是从系统提供的API开始找:

image.png

因为Swift可以随处编写一个类的分类,于是在一个类的分类中定义好该类的通知名这种书写方式随处可见,这样的好处就是通知名与类紧紧联系在一起,一来便于查找,二来便于绑定业务类型。

NotificationCenter.default.post(name: UIApplication.didFinishLaunchingNotification, object: nil)

上面这个通知一发出,通过通知名我就知道是涉及UIApplication的操作行为。

说完了系统提供的API,我们再来看看一些知名第三方库是怎么定义吧,这里以Alamofire为例:

image.png

Alamofire保持了和系统API一样的风格来定义通知名。

我们再来看看Kingfisher

image.png

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客户端。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYsNrDeg' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片