【发布时间】:2014-06-29 14:56:46
【问题描述】:
我正在尝试找出最聪明、最可靠的方法,让多个视图控制器可以访问我检索到的 PubNub 历史记录。正如我所看到的,有多种方法可以做到这一点,但是在阅读了一堆问题和文章之后,我无法决定哪种解决方案是最好的。实际上,我认为依赖注入在我的情况下是正确的想法,但我不确定,因为我在示例 PubNub 应用程序中看到了不同的解决方案,总的来说我从未听说过,所以如果可能的话,我会避免它。
可能的方法:
1.使用 AppDelegate
这可能是最简单的方法,但很多开发人员表示,AppDelegate 确实不是存储全局数据的最佳位置。所以我不想这样做。
2。使用单例
例如,我在 PubNub 的 iPad 演示应用程序(PNDataManager 文件)中看到了这个解决方案。我确信这是最好的方法,但是在我阅读Stephen Poletto's article on objc.io about singletons 之后,我改变了主意,因为他指出了一些问题,这对我来说可能很重要。
这是一篇非常有用的文章,值得一读,但实际上我只会抓住我认为在我的情况下重要的想法。
“假设我们正在构建一个应用程序,用户可以在其中看到他们的列表 朋友们。他们的每个朋友都有一张头像,我们想要 应用程序能够在设备上下载和缓存这些图像。使用方便的 dispatch_once sn-p,我们可能会发现自己正在编写一个 SPThumbnailCache 单例"
假设我们想要缓存message 数组而不是图像,我们在名为ViewController1 的根视图控制器中使用此方法[PubNub requestFullHistoryForChannel: withCompletionBlock:^(NSArray *message, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error)}]; 检索了该数组。
“我们继续构建应用程序,一切似乎都很好, 直到有一天,当我们决定是时候实施“注销” 功能,因此用户可以在应用程序内切换帐户。突然, 我们手上有一个讨厌的问题:用户特定的状态存储在 一个全局单例。当用户退出应用程序时,我们希望成为 能够清理磁盘上的所有持久状态。否则,我们将离开 隐藏用户设备上的孤立数据,浪费宝贵的磁盘 空间。如果用户退出然后登录新帐户, 我们还希望能够为新的 SPThumbnailCache 用户。这里的问题是,根据定义,单例被假定为“创建一次,永远存在”的实例。您可以想象一些解决上述问题的方法。也许我们可以在用户退出时拆除单例实例
这里的问题是,根据定义,单例被假定为 “创建一次,永远存在”的实例。你可以想象几个 上述问题的解决方案。也许我们可以拆掉 用户退出时的单例实例。我们当然可以使这个解决方案工作,但成本太高了。一方面,我们失去了 dispatch_once 解决方案的简单性,这是一种保证线程安全的解决方案,并且所有调用 [SPThumbnailCache sharedThumbnailCache] 的代码只能获得相同的实例。我们现在需要非常小心使用缩略图缓存的代码的代码执行顺序......由于单例实例没有明确的所有者(即单例管理自己的生命周期),因此很难'关闭一个单身人士。 这里的教训是,应该只为全局状态保留单例,而不是绑定到任何范围。如果状态的范围是任何短于“我的应用程序的完整生命周期”的会话,则该状态不应由单例管理。管理用户特定状态的单例是一种代码异味,您应该重新评估您的设计对象图。"
当用户登录新帐户时,我们应该能够 构建一个全新的 SPThumbnailCache 并与之交互,没有 注意破坏旧的缩略图缓存。老人 视图控制器和旧的缩略图缓存应该被懒惰地清理 在后台自动根据典型规则 对象管理。简而言之,我们应该隔离相关的状态 来自与用户 B 关联的状态的用户 A。
我知道一个NSArray 和PNMessage 对象,不包含图像是不一样的,它更容易处理它们,但我真的很困惑我应该如何处理它们。
最初我会将requestFullHistoryForChannel: withCompletionBlock: 中的message 变量传递给名为self.messageGlobal 的实例变量(我可以在每个视图中使用单例)并在用户注销时将其重置。
//inside the viewWillAppear
[PubNub requestFullHistoryForChannel: withCompletionBlock:^(NSArray *message, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error)
// self.messageGlobal should be managed by a singleton or appdelegate or use the dependency injection??
self.messageGlobal = message;
}];
- (IBAction)logOutButton:(id)sender {
//disconnect from the PubNub network
[PubNub unsubscribeFromChannel:currentUserChannel];
//prepape ivar for the new message history
[self.messageGlobal removeAllObjects];
// log out user (i'm using parse.com for managing users)
[PFUser logOut]
}
在斯蒂芬的文章之后,我觉得我迷路了,如果有人能解释正确的方向,那就太棒了。
我的计划是在ViewController1 中创建一个方法来处理历史记录。
-(void)downloadPubNubHistory {
[PubNub requestFullHistoryForChannel: withCompletionBlock:^(NSArray *message, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error)
// self.messageGlobal should be managed by a singleton or appdelegate or use the dependency injection??
self.messageGlobal = message;
}];
}
在AppDelegate 或ViewController1 中,我会放置一个观察者以在当前用户频道收到新消息时得到通知,这很重要,因为我希望每次他或她收到新消息时都拨打downloadPubNubHistory 并且使用新内容更新当前视图。
[[PNObservationCenter defaultCenter] addMessageReceiveObserver:currentUserChannel withBlock:^(PNMessage * msg) {
[ViewController1 downloadPubNubHistory];
} }];
例如,在ViewController3 中,我列出了 sampleUserB 发送到 sampleUserA(当前用户)的频道的每条消息,如果 sampleUserA's 频道在她/他的频道上收到来自 sampleUserB 的新消息,我需要重新加载 downloadPubNubHistory,还需要重新加载 ViewController3,因为我将 ViewController3 中的 self.messageGlobal 过滤为仅从sampleUserB 获取消息。
欢迎任何意见和建议,我可能误解了整个概念,我基本上可以使用单例并在每次用户注销时重置它而没有任何问题,但我想使用最轻量级的可靠解决方案。如果有任何其他推荐的技术,我也很想听听。
【问题讨论】:
标签: ios objective-c pubnub