将来自PubNub历史的消息作为“全局变量”处理。 [英] Handling Messages from PubNub History as a "Global Variable"

查看:92
本文介绍了将来自PubNub历史的消息作为“全局变量”处理。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找出最智能,最可靠的方法,使我可以为多个视图控制器访问检索到的PubNub历史记录。我看到有多种方法可以做到这一点,但在我读过一堆问题和文章后,我无法确定哪种解决方案最好。实际上我认为依赖注入在我的情况下是正确的想法,但我不确定,因为我在示例PubNub应用程序中看到了不同的解决方案,总体而言我从未听说过,所以我会避免它,如果可能的话。

I'm trying to figure out the smartest, most reliable way to make my retrieved PubNub history accessible for several view controllers. As i see there are multiple ways to do that, but after a bunch of questions and articles i've read i can't decide which solution would be the best. Actually i think dependency injection would be the right idea in my case, but i'm not sure because i saw different solutions in the sample PubNub apps and overall i never heard about that so i would avoid it, if it's possible.

可能的方式:

1。使用AppDelegate

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

It could be the easiest way, but a lot of developers said, that AppDelegate is really not the best place for storing global data. So i wouldn't like to do this way.

2。使用Singleton

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

As an instance,i saw this solution in the PubNub's iPad demo app (PNDataManager file). I was sure this is the best way, but after i read Stephen Poletto's article on objc.io about singletons i've changed my mind, because he pointed to some issues, that can be substantial in my case.

这是一篇非常有用的文章,值得一读,但实际上我只会抓住在我的情况下发现重要的想法。

It's a really useful article, that's worth reading, but actually i will grab only the thoughts that i found important in my situation.


假设我们正在构建一个应用程序,用户可以看到他们的
朋友列表。他们的每个朋友都有一个个人资料图片,我们希望
应用程序能够在设备上下载和缓存这些图像。使用dispatch_once代码段,我们可能会发现自己编写了一个SPThumbnailCache单例

"suppose we’re building an app where users can see a list of their friends. Each of their friends has a profile picture, and we want the app to be able to download and cache those images on the device. With the dispatch_once snippet handy, we might find ourselves writing an SPThumbnailCache singleton"

假设我们要缓存消息数组而不是我们使用此方法检索的图像 [PubNub requestFullHistoryForChannel:withCompletionBlock:^(NSArray * message,PNChannel * channel,PNDate * fromDate,PNDate * toDate,PNError * error)}]; 在我们的根视图控制器中名为 ViewController1

Suppose we want to cache the message array instead of images, that we retrieved with this method [PubNub requestFullHistoryForChannel: withCompletionBlock:^(NSArray *message, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error)}]; in our root view controller called ViewController1.


我们继续构建应用程序,一切看起来都很好,直到有一天,当我们决定它时,
是时候实现'注销'
功能了,所以用户可以在应用程序内切换帐户。突然,
我们手上有一个讨厌的问题:用户特定的状态存储在
a全球当用户退出应用程序时,我们想要
能够清理磁盘上的所有持久状态。否则,我们将在用户设备上留下
孤立数据,浪费宝贵的磁盘
空间。如果用户退出然后登录新帐户,
我们也希望能够为新的
用户提供新的SPThumbnailCache。问题在于单身人士根据定义,假设是创造一次,永远活着的实例。你可以设想一些上述问题的解决方案。也许我们可以在用户退出时拆除单例实例

"We continue building out the app, and all seems well in the world, until one day, when we decide it’s time to implement the ‘log out’ functionality, so users can switch accounts inside the app. Suddenly, we have a nasty problem on our hands: user-specific state is stored in a global singleton. When the user signs out of the app, we want to be able to clean up all persistent states on disk. Otherwise, we’ll leave behind orphaned data on the user’s device, wasting precious disk space. In case the user signs out and then signs into a new account, we also want to be able to have a new SPThumbnailCache for the new user. The problem here is that singletons, by definition, are assumed to be "create once, live forever" instances. You could imagine a few solutions to the problem outlined above. Perhaps we could tear down the singleton instance when the user signs out

这里的问题是,根据定义,单身人士被认为是
创造一次,永远活着的实例。您可以想象一下上面提到的问题的几个
解决方案。当用户注销时,也许我们可以拆掉
单例实例。我们当然可以使这个解决方案有效,但成本太高了。首先,我们已经失去了dispatch_once解决方案的简单性,这是一种保证线程安全的解决方案,并且所有调用[SPThumbnailCache sharedThumbnailCache]的代码只能获得相同的实例。我们现在需要非常小心使用缩略图缓存的代码的代码执行顺序....由于单例实例没有明确的所有者(即单例管理自己的生命周期),因此变得非常困难。关闭'单身人士'。 这里的教训是,单身人士只应保留为全球状态,而不是与任何范围相关联。如果state的范围限于任何短于我的应用程序的完整生命周期的会话,则该状态不应由单例管理。管理用户特定状态的单例是代码味道,您应该批判性地重新评估您的设计对象图。

The problem here is that singletons, by definition, are assumed to be "create once, live forever" instances. You could imagine a few solutions to the problem outlined above. Perhaps we could tear down the singleton instance when the user signs out..We could certainly make this solution work, but the cost is far too great. For one, we’ve lost the simplicity of the dispatch_once solution, a solution which guarantees thread safety and that all code calling [SPThumbnailCache sharedThumbnailCache] only ever gets the same instance. We now need to be extremely careful about the order of code execution for code that utilizes the thumbnail cache.... Since there’s no distinct owner for the singleton instance (i.e. the singleton manages its own lifecycle), it becomes very difficult to ever ‘shut down’ a singleton. The lesson here is that singletons should be preserved only for state that is global, and not tied to any scope. If state is scoped to any session shorter than "a complete lifecycle of my app," that state should not be managed by a singleton.A singleton that’s managing user-specific state is a code smell, and you should critically reevaluate the design of your object graph."

当用户登录新帐户时,我们应该能够
构建并与全新的SPThumbnailCache交互没有
注意破坏旧的缩略图缓存。旧的
视图控制器和旧的缩略图缓存应该在后台根据自己的需要懒得清理
,基于
对象管理的典型规则。简而言之,我们应该将与用户A关联的
状态与用户B关联的状态隔离开来。

When the user signs in to a new account, we should be able to construct and interact with a brand new SPThumbnailCache, with no attention paid to the destruction of the old thumbnail cache. The old view controllers and old thumbnail cache should be cleaned up lazily in the background on their own accord, based on the typical rules of object management. In short, we should isolate the state associated with user A from the state associated with user B.

我知道一个 NSArray PNMessage 对象,不包含图片不是同样,它更容易处理它们,但我很想我很困惑应该如何处理它们。

I know one NSArray with PNMessage objects, that doesn't contain images is not the same and it's easier to handle them, but i'm really confused how should i deal with them.

最初我会在 requestFullHistoryForChannel中传递消息变量:withCompletionBlock:到名为 self.messageGlobal 的实例变量(我可以在每个视图中使用单例)并在用户注销时重置它。

Originally i would pass the message variable inside the requestFullHistoryForChannel: withCompletionBlock: to an instance variable called self.messageGlobal (that i can use with a singleton in every views) and reset it when the user logs out.

//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] 
} 

在斯蒂芬的文章之后我觉得自己迷失了,如果有人能解释正确的方向,那就太棒了。

After Stephen's article i feel i'm lost, it would be amazing if somebody could explain the right direction.

我的计划是在 ViewController1 中创建一个处理历史记录的方法。

My plan is to create a method in the ViewController1, that handles the history.

-(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 每当他或她收到新消息并使用新内容更新当前视图时。

In the AppDelegate or ViewController1 i would place an observer to get notified when the current users channel recieved a new message, it's important because i would like the call downloadPubNubHistory everytime he or she receives a new message and update the current view with the new content.

[[PNObservationCenter defaultCenter] addMessageReceiveObserver:currentUserChannel withBlock:^(PNMessage * msg) { 

  [ViewController1 downloadPubNubHistory]; 

 } }]; 

例如在 ViewController3 中我列出每条消息 sampleUserB 发送到 sampleUserA (当前用户)的频道,如果 sampleUserA的频道收到来自 sampleUserB的新消息在她/他的频道上我需要重新加载 downloadPubNubHistory ,还要重新加载 ViewController3 ,因为我正在过滤 self.messageGlobal ViewController3 中仅从 sampleUserB 。

For example in ViewController3 i list every message that was sent by sampleUserB to the channel of sampleUserA (current user), if sampleUserA's channel receives a new message from sampleUserB on her/his channel i need to reload downloadPubNubHistory, and also reload ViewController3, because i'm filtering the self.messageGlobal in the ViewController3 to get messages only from sampleUserB.

欢迎任何意见和建议,我可能误解了整个概念,我基本上可以使用单例并在用户每次注销时重置它而没有任何问题,但我我想利用最轻便可靠的解决方案。如果有任何其他推荐的技术,我也很乐意听。

Any opinion and suggestion welcomed, it's possible that i misunderstood the whole concept and i could basically use singleton and reset it everytime when the user log out without any problems, but i would like to utilize the most lightweight reliable solution. If there is any other recommended technique i would love to hear it too.

文章的原始来源

推荐答案

对我来说,单身总是一个服务的工具具体目的。我没有看到任何麻烦事件多用户和他们的开关基于单身(你总是可以重置单身的状态,而不是试图破坏它)。

因为我们使用数据工作很多,我们可以'当我们需要使用它时,我们总是会初始化一些数据模型,因为会花费额外的时间:分配和分配。初始化,预置初始状态,可能从文件系统或网络加载一些数据。如果我们将在我们想要使用数据操作的每个视图或数据对象中执行所有这些步骤 - 它将会破坏我们的应用程序响应能力,并且用户将有一些糟糕的体验。

所以,这一切都取决于如何你将编写你的单身人士以及你将如何使用它。如果您有多用户应用程序,并且某些敏感数据应远离其他用户,您可以创建一些用户实体并将所有必需数据存储在其中(在您的情况下,消息可以传递给它)。这个实体将是一些简单的数据模型或数据对象,但仍然需要有一些类负责它。在这里,您可以创建一些单件,负责管理当前用户及其数据(当您指定当前用户时,旧的可以解除分配,并且所有数据都可以推送到某些本地存储,如sqlite上的CoreData)。

据我所知,您聊天应用程序想要在登录后提取用户历史记录...您可以在课堂上进行操作,这将管理用户实体并在当前用户更改后立即获取历史记录(在您举例中,您调用历史记录API)每次,当新消息到达用户时 - 糟糕的主意,因为历史API可能)。您的PFUser实例可以存储所有必需的数据,以及应该订阅或取消订阅的频道,并且可以在 logOut 过程中使用它们。

For me, singleton always was a tool which is served for concrete purpose. I don't see any troubles event with multiuser and their switch based on singleton (you can always reset state of singleton and not try to destroy it).
Because we work a lot with data, we can't afford to initialize some data model all the time when we need to use it, because there will be spend additional time on: allocation & initialization, presetting initial state, maybe loading some data from file system or network. If we will perform all this steps in each view or data object where we would like to manipulate with data - it will kill our app responsiveness and user will have some bad experience.
So, it all depends on how you will code your singleton and how you will use it. If you have multiuser app and some sensitive data should be keep away from another user you can create some User entities and store all required data in it (in your case messages can be passed to it). This entity will be some simple data model or data object and still you will be required to have some class responsible for it. Here you can create some singleton which will be responsible for managing current user and his data (when you specify current user, old one can be deallocated and all data can be pushed into some local storage like CoreData on sqlite).
As I understand, you chat application want to pull out user history after login... You can do it in class which will manage User entity and fetch history as soon as current user will be changed (in you example you call history API each time, when new message arrive to the user - bad idea because history API may be heavy). Your PFUser instance can store all required data as for channels on which it should be subscribed or unsubscribed and they can be used during logOut process.

这篇关于将来自PubNub历史的消息作为“全局变量”处理。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆