美文网首页iOS开发(OC)
iOS APP后台向iOS借点时间

iOS APP后台向iOS借点时间

作者: Puiwah_Wai | 来源:发表于2016-07-04 14:46 被阅读865次

    使用UIApplication的beginBackgroundTaskWithExpirationHandler:实例方法。在你完成任务后,调用UIApplication的endBackgroundTask:方法。

    what?

    当一个iOS应用被送到后台,它的主线程会被暂停。你用NSThread的detachNewThreadSelector:toTarget:withObject:类方法创建的线程也被挂起了。如果你想在后台完成一个长期任务,就必须调用UIApplication的beginBackgroundTaskWithExpirationHandler:实例方法,来向iOS借点时间。UIApplication的backgroundTimeRemaining属性包含了程序完成他的任务可以使用的秒数。如果在这个期限内,长期任务没有被完成,iOS将终止程序。每个对beginBackgroundTaskWithExpirationHandler:方法的调用,必须要相应的调用endBackgroundTask:方法(UIApplication的另一个实例方法)。也就是说,如果你向iOS要更多时间来完成一个任务,你必须告诉iOS你什么时候能完成那个任务和其所有被暂停的线程被放入后台。

    当你的程序在前台时,UIApplication的backgroundTimeRemaining属性等于DBL_MAX常量,这是double类型可表示的最大值(和这个值相当的integer通常等于-1)。在iOS被要求在程序被完全挂起之前给于更多的执行时间,这个属性指明了在完成任务前程序拥有多少秒。

    在程序中你可以多次调用beginBackgroundTaskWithExpirationHandler:方法。要记住的重点是,当iOS为你的程序返回一个token或者任务标识(task

    identifier)时,你都必须调用endBackgroundTask:方法,在运行的任务结束时,用来标志任务结束。如果你不这么做的话,iOS会终止你的程序。

    在后台时,程序不应该执行完全的功能,也不应该处理大量数据。事实上,他们只应该完成一个长期任务。

    比如,一个程序正在调用一个web service

    API,并且还没有从服务器上的那个API接收到响应。在此期间,如果程序被送入后台,它可以请求更多的时间,直到它从服务器收到响应。一旦响应被接收,程序必须保存其状态,并调用UIApplication的endBackgroundTask:实例方法将任务标记为完成。

    让我们看一个例子。我将从在应用程序委托中定义一个UIBackgroundTaskIdentifier类型的属性开始。同时,让我们定义一个NSTimer,当程序被送到后台时,我们将用它每隔1秒向控制台窗口输出一条消息:

    #import

    @interfaceCompleting_a_Long_Running_Task_in_the_BackgroundAppDelegate :UIResponder

    @property (nonatomic, strong) UIWindow*window;

    @property (nonatomic, unsafe_unretained)UIBackgroundTaskIdentifierbackgroundTaskIdentifier;

    @property (nonatomic, strong) NSTimer*myTimer;

    @end

    接下来我们继续同步属性:

    #import"Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate.h"@implementationCompleting_a_Long_Running_Task_in_the_BackgroundAppDelegate

    @synthesize window = _window;

    @synthesize backgroundTaskIdentifier; @synthesizemyTimer;

    现在,让我们创建定时器,并在程序被送到后台时启动它:

    - (BOOL) isMultitaskingSupported{

    BOOL result = NO;

    if ([[UIDevice currentDevice]

    respondsToSelector:@selector(isMultitaskingSupported)]){ result= [[UIDevice currentDevice]isMultitaskingSupported];

    }

    return result;

    }

    - (void) timerMethod:(NSTimer*)paramSender{

    NSTimeInterval backgroundTimeRemaining =

    [[UIApplication sharedApplication]backgroundTimeRemaining];

    if (backgroundTimeRemaining == DBL_MAX){ NSLog(@"Background TimeRemaining = Undetermined");

    } else {iOS 5 Programming

    Cookbookwww.devdiv.com翻译整理

    DevDiv翻译:kyelup cloudhsu耐心摩卡wangli2003j3 xiebaochun dymx101 jimmylianf BeyondVincent21DevDiv校对:laigb kyelup DevDiv编辑:BeyondVincent版本1.0 |

    2012年07月30日

    NSLog(@"Background Time Remaining = %.02fSeconds",

    backgroundTimeRemaining);

    } }

    - (void)applicationDidEnterBackground:(UIApplication*)application{

    if ([self isMultitaskingSupported] == NO){

    return; }

    self.myTimer =

    [NSTimerscheduledTimerWithTimeInterval:1.0f

    target:self

    selector:@selector(timerMethod:)userInfo:nil

    repeats:YES];

    self.backgroundTaskIdentifier=

    [application beginBackgroundTaskWithExpirationHandler:^(void) {[self endBackgroundTask];

    }]; }

    你可以看到,在后台任务的完成处理者(completion

    handler)中,我们调用了应用程序委托的endBackgroundTask方法。这是一个我们编写的方法,如下:

    - (void) endBackgroundTask{

    dispatch_queue_t mainQueue =dispatch_get_main_queue();

    __weakCompleting_a_Long_Running_Task_in_the_BackgroundAppDelegate*weakSelf = self;

    dispatch_async(mainQueue, ^(void) {

    Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate*strongSelf = weakSelf;

    if (strongSelf != nil){

    [strongSelf.myTimer invalidate];

    [[UIApplication sharedApplication]endBackgroundTask:self.backgroundTaskIdentifier];

    strongSelf.backgroundTaskIdentifier= UIBackgroundTaskInvalid;}

    }); }

    在长期任务结束后,我们需要做一些事情进行清理:

    1.结束所有的线程和定时器,不管他们是基础定时器还是GCD中创建的。

    2.调用UIApplication的endBackgroundTask:方法来结束后台任务。

    3.将任务标识设置为UIBackgroundTaskInvalid,标志我们的任务结束。

    最后,当我们的应用回到前台,如果我们的后台任务还在执行中,我们需要确保我们在干掉它:

    - (void)applicationWillEnterForeground:(UIApplication*)application{

    if (self.backgroundTaskIdentifier!=UIBackgroundTaskInvalid){

    [self endBackgroundTask]; }

    }

    在我们的例子中,不论何时程序被送到后台,我们都会要求更多时间以完成一个长期任务(例如,在这里是我们计时器的代码)。在我们的时间里,我们不断的读取UIApplication实例中backgroundTimeRemaining属性的值,将它打印到控制台。在UIApplication的beginBackgroundTask

    WithExpirationHandler:实例方法中,在程序的额外时间内完成一个长期任务之前,我们提供的代码将被执行(一版大概在任务过期前5到10秒)。在此,我们只要调用UIApplication的endBackgroundTask:实例方法来结束任务。

    相关文章

      网友评论

        本文标题:iOS APP后台向iOS借点时间

        本文链接:https://www.haomeiwen.com/subject/uencjttx.html