使用多个beginBackgroundTaskWithExpirationHandler调用 [英] Using multiple beginBackgroundTaskWithExpirationHandler calls

查看:78
本文介绍了使用多个beginBackgroundTaskWithExpirationHandler调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在此处关注此先前的帖子:

I am trying to follow this previous post here: Best practice to send a lot of data in background on iOS4 device?

基本上,我有一个名为getRequest的方法,该方法从Web服务器获取信息.我需要从Web服务器中获取大约50条数据.因此,与此同时,我有50个对connectionDidFinishLoading的委托调用.目前,我的getRequest如下:

And basically, I have a method called getRequest that grabs information from the web server. There are about 50 pieces of data I need from the web server. So at the same time, I have 50 delegate calls to connectionDidFinishLoading. Currently my getRequest looks like:

-(void) getRequestWithURL:(NSString *) requestURL 
{
    static int getRequest = 0;
    NSLog(@"getRequest: %i", getRequest);
    getRequest++;

    UIApplication *app = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier taskID;
    taskID = [app beginBackgroundTaskWithExpirationHandler:^{

        NSLog(@"Time remaining: %f", app.backgroundTimeRemaining);

        NSLog(@"Background task not completed");
        [app endBackgroundTask:taskID];
    }];

    NSURLRequest *req = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:requestURL]];
    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:req delegate:self] ; 
    [self startRequestWithConnection:con];
    [req release];

    if (taskID == UIBackgroundTaskInvalid) {
        NSLog(@"Failed to create background task identifier");
    }

}

然后在我的连接中DidFinishLoading:

Then in my connectionDidFinishLoading:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        // process data from server
   // endBackgroundTask:someTaskID???
}

我知道您可以多次调用beginBackgroundTaskWithExpirationHandler,但是我不知道我在getRequest方法中正在做什么,因为每次调用该方法时我只有一个变量__block UIBackgroundTaskIdentifier taskID.而且我也不确定是否需要为每个对getRequest的调用在connectionDidFinishLoading方法中调用endBackgroundTask,因为您应该平衡beginBackgroundTaskWithExpirationHandler与endBackgroundTask:调用.如果是这样,由于我的getRequest当前不具有该基础结构,该怎么办?我是否需要50个ivars才能使connectionDidFinishLoading方法看到对getRequest的50个初始调用?谢谢.

I know you are allowed to have multiple calls of beginBackgroundTaskWithExpirationHandler, but I don't know if what I'm doing in my getRequest method is doing that since I only have one variable __block UIBackgroundTaskIdentifier taskID each time the method is called. And I'm also not sure if I need to call endBackgroundTask in the connectionDidFinishLoading method for each call to getRequest since you are supposed to balance the beginBackgroundTaskWithExpirationHandler with an endBackgroundTask: call. If so, how do I do that since my getRequest doesn't currently have that infrastructure? Do I need 50 ivars in order for the connectionDidFinishLoading method to see the 50 initial calls to getRequest? Thanks.

推荐答案

如您所说,您需要在beginBackgroundTaskWithExpirationHandler通话与endBackgroundTask通话之间取得平衡.

As you said, you need to balance beginBackgroundTaskWithExpirationHandler call with an endBackgroundTask call.

我想到的一个解决方案是这样的:

One solution I have in mind looks like this:

创建一个新的实例变量

UIBackgroundTaskIdentifier backgroundTaskID;

无论如何,您都在计数请求,因此您也可以在connectionDidFinishLoading中减少getRequest:

You are counting the requests anyway so you could also decrement getRequest in connectionDidFinishLoading:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    // process data from server
    getRequest--;

    if (getRequest == 0 && backgroundTaskID != UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
        backgroundTaskID = UIBackgroundTaskInvalid;
    }
}

现在,最后一个请求完成后,后台任务结束.要仅启动一个后台任务,您可以使用一种方法来启动它,该方法会在应用程序进入后台时被调用.

Now the background task gets ended after the last request has been completed. To start only one background task you start it in a method that gets called when the app goes to the background.

您需要收听UIApplicationDidEnterBackgroundNotification

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(applicationDidEnterBackground)
                                             name:UIApplicationDidEnterBackgroundNotification
                                           object:nil];

并实现该方法

- (void)applicationDidEnterBackground:(NSNotification *)notification
{
    if (getRequest > 0) {
        backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
            [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
            backgroundTaskID = UIBackgroundTaskInvalid;
         }];
    }
}

现在,您只有一个正在运行的后台任务,当您的应用程序进入后台时它会自动启动,并且您正在运行的请求会在所有请求完成后终止.

Now you only have one running background task that starts automatically when your app goes to the background and you have running requests that gets ended when all your requests are done.

另一个改进是将您的网络请求添加到NSOperationQueue中,以避免手动计数并限制并发请求的数量.

Another improvement would be to add your network requests to an NSOperationQueue to avoid the manual counting and limit the number of concurrent requests.

这篇关于使用多个beginBackgroundTaskWithExpirationHandler调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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