处理来自PubNub历史的消息作为“全局variables”

我试图找出最聪明,最可靠的方法,使我检索的PubNub历史访问多个视图控制器。 正如我所看到的那样,有多种方法可以做到这一点,但是在阅读完一堆问题和文章之后,我无法决定哪种解决scheme是最好的。 其实我认为在我的情况下,dependency injection是正确的想法,但我不知道,因为我看到在示例PubNub应用程序中的不同解决scheme,总体上我从来没有听说过,所以我会避免它,如果可能的话。

可能的方法:

1.使用AppDelegate

这可能是最简单的方法,但很多开发人员说,AppDelegate实际上不是存储全局数据的最佳位置。 所以我不想这样做。

2.使用Singleton

作为一个例子,我在PubNub的iPad演示程序( PNDataManager文件)中看到了这个解决scheme。 我确信这是最好的办法,但是在我读了Stephen Poletto关于objc.io的关于单身人士的文章之后,我改变了主意,因为他指出了一些问题,对我来说可能是相当重要的 。

这是一篇非常有用的文章,值得一读,但实际上我只会抓住我认为重要的想法。

“假设我们正在构build一个应用程序,让用户可以看到他们的朋友列表,他们的每个朋友都有个人资料图片,我们希望应用程序能够下载和caching设备上的这些图片。 ,我们可能会发现自己写了一个SPThumbnailCache单例“

假设我们想cachingmessage数组,而不是图像,我们用这个方法检索[PubNub requestFullHistoryForChannel: withCompletionBlock:^(NSArray *message, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error)}]; 在我们的根视图控制器中调用ViewController1

“我们继续构build应用程序,一切似乎都在世界上,直到有一天,当我们决定实施”注销“function的时候,用户可以在应用程序内切换帐户。突然,我们有一个讨厌的问题在我们的手中:特定于用户的状态存储在全局单例中,当用户注销应用程序时,我们希望能够清除磁盘上的所有持久状态,否则我们会在用户的数据上留下孤立的数据设备,浪费宝贵的磁盘空间,如果用户注销并签入新帐户,我们也希望能够为新用户提供一个新的SPThumbnailCache,这里的问题在于,是“创造一次,永远活着”的例子,你可以设想一些上述问题的解决scheme,也许我们可以在用户注销时拆除单例实例

这里的问题是,按照定义,单身人士被认为是“创造一次,永远活着”的例子。 您可以想象一下上面概述的问题的一些解决scheme。 也许我们可以在用户注销时拆除单例实例。我们当然可以使这个解决scheme起作用,但是成本太高了。 一方面,我们失去了dispatch_once解决scheme的简单性,这是一个保证线程安全的解决scheme,所有调用[SPThumbnailCache sharedThumbnailCache]的代码都只能得到相同的实例。 我们现在需要对使用缩略图caching的代码的执行顺序非常小心。因为对于单例实例(即单例pipe理自己的生命周期)没有明显的所有者,所以很难“closures“一个单身人士。 这里的教训是,单身人士应该只保留在全球的国家,而不是任何范围。 如果状态的范围小于“我的应用程序的完整生命周期”的任何一个会话,则该状态不应该由单例pipe理。pipe理用户特定状态的单例是一种代码异味,您应该批判性地重新评估您的devise对象图。

当用户login到一个新帐户时,我们应该能够构build一个全新的SPThumbnailCache并与之交互,而不必关注销毁旧的缩略图caching。 旧的视图控制器和旧的缩略图caching应该根据典型的对象pipe理规则,在后台自动清理。 简而言之,我们应该将与用户A相关联的状态从与用户B相关联的状态中分离出来。

我知道一个NSArrayPNMessage对象,不包含图像是不一样的,它更容易处理,但我真的很困惑,我应该如何处理它们。

最初,我会将requestFullHistoryForChannel: withCompletionBlock:messagevariablesrequestFullHistoryForChannel: withCompletionBlock:传递给名为self.messageGlobal (我可以在每个视图中使用一个单例)的实例variables,并在用户注销时将其重置。

 //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创build一个处理历史logging的方法。

 -(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; }]; } 

AppDelegateViewController1当当前用户频道接收到新消息时,我会让观察者得到通知,这很重要,因为每次他或她收到新消息并使用新内容更新当前视图时,我都会想要调用downloadPubNubHistory

 [[PNObservationCenter defaultCenter] addMessageReceiveObserver:currentUserChannel withBlock:^(PNMessage * msg) { [ViewController1 downloadPubNubHistory]; } }]; 

例如在ViewController3我列出了sampleUserB发送给sampleUserA (当前用户)的通道的每条消息,如果sampleUserA的通道从她/他的通道上的sampleUserB收到一条新消息,我需要重新加载downloadPubNubHistory ,并重新加载ViewController3 ,因为我在ViewController3筛选self.messageGlobal以仅从sampleUserB获取消息。

任何意见和build议表示欢迎,这可能是我误解了整个概念,我可以基本上使用单身,每当用户注销没有任何问题时重置它,但我想利用最轻量级的可靠的解决scheme。 如果还有其他推荐的技术,我也很乐意听到。


文章的原始来源

对我而言,单身人士总是成为具体目的的工具。 我没有看到多用户和他们的开关基于单身(任何时候你可以重置单身的状态,而不是试图摧毁它)任何麻烦事件。
因为我们在数据方面做了很多工作,所以在我们需要使用它的时候,我们不能始终初始化一些数据模型,因为会花费额外的时间:分配和初始化,预设初始状态,文件系统或networking。 如果我们将在每个视图或数据对象中执行所有这些步骤(我们想要使用数据进行操作),它将会终止我们的应用程序响应,并且用户将会遇到一些不好的体验。
所以,这一切都取决于你将如何编码你的单身人士,你将如何使用它。 如果你有多用户的应用程序和一些敏感的数据应该远离另一个用户,你可以创build一些用户实体,并存储所有需要的数据(在你的情况下,消息可以传递给它)。 这个实体将是一些简单的数据模型或数据对象,仍然需要有一些类负责它。 在这里,你可以创build一些单身人士,负责pipe理当前用户和他的数据(当你指定当前用户时,旧的可以被解除分配,所有的数据可以被压入一些本地存储,如CoreData上的SQLite)。
据我所知,你聊天的应用程序想要在login后拔出用户历史logging…你可以在课程中做到这一点,它将pipe理用户实体并获取历史logging,一旦当前用户将被改变(在你的例子中你每次调用历史API ,当新消息到达用户 – 由于历史API可能会很重的坏主意)。 您的PFUser实例可以存储所有需要的数据,这些数据应该是订阅或取消订阅的渠道,并且可以在logOut过程中使用。