服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - 详解iOS中跨页面状态同步方案比较

详解iOS中跨页面状态同步方案比较

2021-05-27 16:26Tpphha IOS

这篇文章主要介绍了详解iOS中跨页面状态同步方案比较,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

由于团队希望项目能够去 coredata 化,而以往状态同步都是依赖于 coredata 的nsfetchedresultscontroller。因此去 coredata 则必须寻找一种替代方案来进行状态同步。

notificationcenter

状态同步实际是一对多的场景,也就是一个事件可以被多个观察者监听到。而苹果的系统框架自带的 notificationcenter 正是用来适配这种场景,并且其也是被系统框架本身及我们开发者大面积使用的。用法如下:

  1. 定义通知名字,以及需要额外传递信息的 key
  2. 基于 target-action 的方式注册通知
?
1
open func addobserver(_ observer: any, selector aselector: selector, name aname: nsnotification.name?, object anobject: any?)

实现监听通知的方法

?
1
func onreceivednotification(note: nsnotification)

发送通知,可以传递发送通知的对象(object)以及一些额外的信息(userinfo)

?
1
open func post(name aname: nsnotification.name, object anobject: any?, userinfo auserinfo: [anyhashable : any]? = nil)

移除注册的通知

?
1
open func removeobserver(_ observer: any, name aname: nsnotification.name?, object anobject: any?)

当然 notificationcenter 也提供了一种更加便利基于 block 的方式注册监听通知,其将 2,3 两个步骤整合为 1 个步骤。

?
1
open func addobserver(forname name: nsnotification.name?, object obj: any?, queue: operationqueue?, using block: @escaping (notification) -> void) -> nsobjectprotocol

整体流程很清晰,简单易用,但是却有一个严重的缺点 —— 弱类型。我们接收到的是一个nsnotification对象。

?
1
2
3
4
5
open class nsnotification : nsobject, nscopying, nscoding {
  open var name: nsnotification.name { get }
  open var object: any? { get }
  open var userinfo: [anyhashable : any]? { get }
}

假设我们需要传递一个关注状态改变的信息,那么需要包含关注更改后的状态以及被关注者的 id。那么我们需要从 userinfo 中取出所需要的值:

?
1
2
let following = notification.userinfo["followingkey"] as! nsnumber
let userid = notification.userinfo["useridkey"] as! nsnumber;

也就是说接收通知的一方一般需要要查看文档才知道怎样从 userinfo 取值,取的值的类型又是什么。这对于使用是极为不方便的。

swiftnotificationcenter

swiftnotificationcenter是一种面向协议的通知中心方案。使用方式如下:

定义协议

?
1
2
3
protocol followingchanged {
  func followingdidchange(following: bool, userid: nsnumber)
}

基于协议注册通知

?
1
broadcaster.register(update.self, observer: observer)

实现协议方法

?
1
2
3
4
5
extension viewcontroller: followingchanged {
 func followingdidchange(following: bool, userid: nsnumber) {
  // do something
 }
}

发送通知

?
1
2
3
broadcaster.notify(followingchanged.self) {
  $0.followingdidchange(following, userid)
}

移除注册的通知

?
1
broadcaster.unregister(update.self, observer: observer)

我们可以看到,其基于协议的方式解决了弱类型的问题,并且其通过associatedobject实现了通知的自动移除。但其也存在着扩展性较差的问题。

依然是关注改变的场景,假如随着业务的发展,有的地方需要知道关注后是否为互关的状态,那么又需要增加一个字段来标识。因此我们需要修改协议,增加参数,且由于其不是必须传递的参数,因此是 optional 类型。

?
1
2
3
protocol followingchanging {
  func followingdidchange(following: bool, userid: nsnumber, followingeachother: nsnumber?)
}

如果在该类型通知被广泛应用的场景,那么需要修改的地方就尤其多了。这显然也是难以接受的。

eventbus

eventbus 在安卓中被广泛地应用,其流程如下图所示:

 

 
详解iOS中跨页面状态同步方案比较

 

图片来源:eventbus

使用方式如下:

定义事件

?
1
2
3
4
class tpfollowingchangedevent: nsobject, tpevent {
    private(set) var following: bool
        private(set) var userid: nsnumber
}

注册事件

?
1
tpeventbus<tpfollowingchangedevent>.shared.register(eventtype: tpfollowingchangedevent.self, subscriber: self, selector: #selector(onevent(event:object:)))

实现监听事件的方法

?
1
2
3
@objc func onevent(event: tpfollowingchangedevent, object: any?) {
    // do something
}

发送事件

?
1
tpeventbus.shared.post(event: event, object: self)

移除事件的注册

?
1
tpeventbus<tpfollowingchangedevent>.shared.unregister(eventtype: tpfollowingchangedevent.self, subscriber: self)

我们可以看到, eventbus 也是强类型的。

假如依然关注的场景,需要增加 followingeachother 参数,那么我们只需要在 tpfollowingchangedevent 中增加 followingeachother 参数即可。如下所示:

?
1
2
3
4
5
class tpfollowingchangedevent: nsobject, tpevent {
    private(set) var following: bool
        private(set) var userid: nsnumber
    private(set) var followingeachother: nsnumber?
}

因此使用 eventbus 实现了以下需求:

  • 强类型
  • 可扩展

eventbus 同 notificationcenter 都是基于 target-action 的方案,但是我们不难将其扩展为支持 block 监听的方式,并且同样让其能够自动移除事件的注册。类似于如下的使用方式:

?
1
2
3
tpeventbus<tpfollowingchangedevent>.shared.subscribe(eventtype: tpfollowingchangedevent.self).forobject(self).onqueue(operationqueue.main).onevent { (event, object) in
   // do something
}.disposed(by: self)

基于 oc, 我实现了一个小巧但比较全面的 eventbus 供参考:tpeventbus

最后

我们可以看到,一对多场景中观察者模式的应用流程都大同小异,但是如何更好用确是值得深思的。当然以上也只是我在一些使用场景上的思考,肯定会欠缺考虑,欢迎拍砖:blush:。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://juejin.im/post/5d88e7176fb9a06acd456067

延伸 · 阅读

精彩推荐
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01