【问题标题】:ios: Queue blocks in background and execute when network becomes availableios:在后台排队阻塞并在网络可用时执行
【发布时间】:2012-05-30 19:23:59
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

    我们在内部项目中遇到了类似的问题,因此我编写了一个名为 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())
    

    【讨论】:

    • 请将适当的代码添加到您的答案中,而不是链接它
    • 抱歉,添加了一个简单的用例
    【解决方案2】:

    我使用NSOperationQueue 完全符合您的目标。首先,创建一个串行队列并默认挂起:

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

    然后,创建一个可达性实例并注册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
    }]; 
    

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

    【讨论】:

    • 我正在尝试这样的方法,但是当连接返回时,我遇到了“超出范围的 dealloc'd”块的问题。你在调用你的块时遇到了什么麻烦之后?看起来像:“无法恢复当前帧”
    【解决方案3】:

    查看-[PFObject saveEventually]。这应该会自动执行您尝试执行的操作,并且具有抵御应用终止的额外好处。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

        • 谢谢。我查看了 AFNetworking 库,但它似乎更多地用于 NSURL 请求,而不是任何我想仅在互联网可用时才开始执行的任意块(它可能仅将网络连接用于块执行的某些部分)。跨度>
        • 我明白你的意思......可达性答案将是我的下一个想法,但是我看到有人已经充实了这个想法。
        猜你喜欢
        • 1970-01-01
        • 2021-02-26
        • 2011-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-12
        • 1970-01-01
        • 2014-10-16
        相关资源
        最近更新 更多