ios:队列在后台阻塞,并在网络可用时执行

时间:2012-05-24 08:15:44

标签: ios queue grand-central-dispatch reachability parse-platform

我正在使用parse.com API开发一个应用程序(托管后端提供API以在其服务器上保存数据)。我希望能够在线和离线无缝使用该应用程序。 为此,我需要使用一个队列,我可以放置需要网络访问的块。当网络可用时,这些块应该是串行执行的,当网络脱机时,应该暂停队列处理。

我正在考虑将GCD用于暂停/恢复,因为网络可用/不可用。 我想知道是否有更好的选择?如果将应用程序放在后台,这会有效吗?这里的一个例子是,当网络不可用(排队等待)然后将应用程序置于后台时,用户会保存一些数据。现在,当网络可用时,是否可以自动在后台进行保存?

5 个答案:

答案 0 :(得分:16)

我的目标是使用NSOperationQueue。首先,创建一个串行队列并在默认情况下暂停它:

self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
self.operationQueue.maxConcurrentOperationCount = 1;
[self.operationQueue setSuspended:YES];

然后,创建一个Reachability实例并注册kReachabilityChangedNotification

[[NSNotificationCenter defaultCenter] addObserver:manager
                                         selector:@selector(handleNetworkChange:) 
                                             name:kReachabilityChangedNotification 
                                           object:nil];

[self setReachability:[Reachability reachabilityWithHostName:@"your.host.com"]];
[self.reachability startNotifier];

现在,在网络状态发生变化时启动和停止队列:

-(void)handleNetworkChange:(NSNotification *)sender {
    NetworkStatus remoteHostStatus = [self.reachability currentReachabilityStatus];

    if (remoteHostStatus == NotReachable) {
        [self.operationQueue setSuspended:YES];
    }
    else {
        [self.operationQueue setSuspended:NO];
    }
}

您可以使用以下内容对块进行排队:

[self.operationQueue addOperationWithBlock:^{
    // do something requiring network access
}]; 

暂停队列只会阻止操作启动 - 它不会暂停正在进行的操作。在执行操作时,您总是有可能丢失网络,因此您应该在操作中考虑到这一点。

答案 1 :(得分:2)

结帐-[PFObject saveEventually]。这应该做你想要自动执行的操作,并具有抵御应用程序终止的额外好处。

答案 2 :(得分:1)

您是否考虑过使用AFNetworking库?我相信它与Reachabiltiy挂钩,可以完全按照你的意愿行事。

答案 3 :(得分:0)

我是GCD和Blocks的忠实粉丝,但为此我会使用NSOperationQueue构建解决方案。对于低级别的东西,GCD在我看来更多。使用NSOperationQueue,您可以取消某些操作。您还可以表达对其他操作的依赖关系(如果您的应用程序需要这样做)。

答案 4 :(得分:0)

我们在内部项目中遇到了类似的问题,因此我编写了一个名为OfflineRequestManager的pod,它包装任何网络请求并允许它排队,无论连接如何。如果您将Parse请求(或其他)包装在符合OfflineRequest的对象中,则管理器会将其排入队列并确保在连接允许时它就会熄灭。

最简单的用例看起来像

import OfflineRequestManager

class SimpleRequest: OfflineRequest {
    func perform(completion: @escaping (Error?) -> Void) {
        doMyParseThing(withCompletion: { response, error in
            handleResponse(response)
            completion(error)
        })
    }
}
///////
OfflineRequestManager.defaultManager(queueRequest: SimpleRequest())