应用程序激活时刷新视图中的竞争条件

时间:2011-05-02 22:39:12

标签: iphone objective-c cocoa-touch race-condition

在Facebook的iPhone应用程序上,每当应用程序变为活动状态时,新闻源都会刷新。我想做类似的事情,但我担心的是竞争条件。我的应用程序的一般引导如下:

UIApplicationDelegate

- (void)applicationDidFinishLaunching:(UIApplication*)application
{
  [window addSubview:[self.navigationController view];
  [window makeKeyAndVisible];
}

- (void)applicationDidBecomeActive:(UIApplication*)application
{
  [rootViewController refresh];
}

RootViewController的

#pragma mark custom

- (void)refresh
{
  if (self.newsFeedModel == nil) {
   self.newsFeedModel = [[NewsFeedModel alloc] initWithDelegate:self];
  }
  [self.newsFeedModel request];
}

#pragma mark UIViewController

- (void)viewDidLoad
{
  // initialize the table
  // add subviews and whatnot
}

#pragma mark NewsFeedDelegate

- (void)newsFeedSucceeded:(NSMutableArray*)feed
{
  // reload table view with new feed data
}

在任何地方洒上NSLog之后,我确定了操作的顺序:

  1. 的applicationDidFinishLaunching
  2. applicationDidBecomeActive
  3. 刷新
  4. viewDidLoad中
  5. newsFeedSucceeded
  6. 注意在加载根视图之前如何调用refresh。当我们忙于查询服务器时,根视图会加载。当服务器响应时,将使用源填充根视图。这在大多数情况下都适用,因为网络操作需要很长时间。但是,如果网络操作的完成速度比可以加载的视图快,那么我将尝试在加载视图之前构造新闻源。这会很糟糕。解决这种竞争条件的最佳Cocoa Touch练习是什么?我只想设置一堆标志来确定我们所处的状态并根据状态刷新新闻源,但我想知道Cocoa Touch中是否有内置事件来处理这个问题。

1 个答案:

答案 0 :(得分:1)

我想你想看看applicationWillEnterForeground:而不是。

applicationDidBecomeActive:可以在您的应用仍然在前台运行时调用。例如,如果在您的应用程序位于前台并且用户将其取消时发出文本消息,则会调用applicationDidBecomeActive :.

您可以使用NSNotificationCenter在RootViewController中订阅UIApplicationWillEnterForegroundNotification事件。我会在RootViewController initWithNibName:或您使用的任何init方法中执行此操作。

现在你只需要在2个地方调用刷新。一旦在viewDidLoad的末尾,并且每当调用applicationWillEnterForeground:时。

这可以解决你的竞争条件问题。由于RootViewController在知道可以执行此操作时正在处理它自己的刷新。

<强> RootViewController的

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if(self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
    }
    return self;
}

- (void)viewDidLoad
{
    // initialize the table
    // add subviews and whatnot
    [self refresh];
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    [self refresh];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}