• iOS-----后台运行


    后台运行

      当应用程序进入后台时,系统会自动回调应用程序委托的applicationDidEnterBackground:方法。

    应用可以在该方法中完成转入后台前需要做的准备工作,所有的应用需要做以下事情。

      释放所有可以释放的内存。

      保存用户数据或状态信息,所有没写入磁盘的文件或信息,在进入后台之前,都应该写入磁盘,因为程序可能在后台被杀死。

    进入后台时释放内存

        当程序进入后台之后,为了确保获得最佳的用户体验,建议释放那些占用内存较大且可以重新获取的资源----

    这是因为当应用处于后台时,iOS系统会优先终止那些占用内存大的应用。如果应用尽可能释放其所占用的内存,

    那么应用就可以在后台存或更久。从这个角度来看,可以得到一个结论:应用暂停时所占用的内存减少,iOS彻底终止该应用的风险就越低。

    如果应用没有启用ARC机制,程序需要在应用进入后台时,将那些需要释放的资源的引用计数变为0,从而让系统回收这些资源。

    当应用转入前台时,系统需要重新恢复这些资源。

    如果应用启用了ARC机制,程序只要在应用进入后台时,将应用那些需要释放的资源的变量赋为nil即可。当应用转入前台时,

    系统需要重新恢复这些资源。

    //  使用默认的通知中心监听应用转入前台的过程

    //  应用转入前台时会向通知中心发送UIApplicationWillEnterForegroundNotification

    //  从而激发enterFore:方法

    [[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector:@selector(enterBack:) name:UIApplicationWillEnterForegroundNotification

    object:[UIApplication sharedApplication]];

    //  使用默认的通知中心监听应用转入前台的过程

    //  应用转入前台时会向通知中心发送UIApplicationDidEnterBackgroundNotification

    //  从而激发enterFore:方法

    [[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector:@selector(enterBack:) name:UIApplicationDidEnterBackgroundNotification

    object:[UIApplication sharedApplication]];

    说明

    上面程序控制当应用转入前台时,该视图控制器的enterFore:方法被调用;当应用转入后台时,该控制器的enterBack:方法被调用,下面是enterBack:方法的代码

     

    - (void) enterBack:(NSNotification *)notification

    {

       NSLog(@”—enterBack---”);

       // 转入后台时将可以迅速重建,而且占用内存较大的对象设为nil,以便系统释放内存  

    bgLayer1.contents = nil;

    bgLayer2.contents = nil;

    ePlaneImage1 = nil;

    }

    说明

     由于该应用已经启用了ARC机制,因此上面方法只要将这些图片、音乐资源的变量设为nil,系统就可以回收这些图片、音乐资源所占用的内存。

        当应用再次转入前台时,该控制器的enterFore:方法被调用,该方法将负责再次加载这些图片、音乐资源。下面是enterFore:方法的代码。

    代码片段

    -  (void) enterFore:(NSNotification *)notification

    {

        NSLog(@”===enterFore===”);

    bgLayer1.contents = (id)[bgImage CGImage];

    bgLayer2.contents = (id)[bgImage CGImage];

    ePlaneImage1 = [UIImage imageNamed:@”e1”];

    }

    说明

      通过上面的处理方法,程序可以在应用转入后台时释放大部分内存,使得该应用在后台以少量内存运行,从而降低该应用被iOS系统终止的风险。当该应用转入前台时,系统将会再次初始化 这些资源,从而保证iOS应用可以迅速恢复。

    进入后台时保存状态

    当应用进入后台时,如果程序有一些状态数据没有保存,而iOS系统可能在内存紧张时终止该应用,那么就可能导致该应用丢失这些状态数据。

    为了让应用不会丢失状态数据,程序可以在应用转入后台时记录应用状态,应用转入后台时将会调用视图控制器的enterBack:方法,因此在该方法后面增加如下代码:

         // 使用NSUserDefaults存储系统积分

       [[NSUserDefaults standardUserDefaults] setInteger:score forkey:@”score”];

        上面的代码只是简单地使用了NSUserDefault来保存程序状态。如果程序需要保存的状态数据较多,也可采用plist属性文件或者其他形式来保存程序状态。

         接下来同样可以在应用转入前台时恢复程序状态,应用转入前台时将会调用视图控制器的enterFore:方法,因此在该方法后面增加如下代码:

      // 使用NSUserDefaults读取系统已经保存的积分

      NSNumber* scoreNumber;

      if((scoreNumber = [[NSUserDefault standardUserDefaults]

    objectForKey:@”score”]))

    {

        score = scoreNumber.integerValue;

    }

    请求更多的后台时间

       当应用转入后台后,不要在主线程中执行超过5秒的任务,如果应用进入后台花费了太多时间(即applicationDidEnterBackground:方法的执行体花费太多时间),应用可能从内存中被删除.

       假如应用程序正在执行文件下载或文件传输等,当应用进入后台时,如果该任务还没有执行完成,应用转入后台该任务就会被暂停.千万不要强制在applicationDidEnterBackground:方法中直接完成该任务----因为这会导致应用进入后台花费太多时间,iOS系统可能直接从内存中删除该应用.正确的做法是: 以applicationDidEnterBackground:方法为平台,告诉系统进入后台还是更多的任务需要完成,从而向系统申请更多的后台时间.在这种方式下,当我们的应用处于后台时,即使用户正在使用其他应用,只要系统还是足够的内存,我们的应用就可以保存在内存中,iOS系统会保留应用运行一段时间。

    为了请求更多的后台时间,按如下步骤执行:

    1.调用UIApplication对象的beginBackgroundTaskWithExpirationHandler:方法请求获取更多的后台执行时间,该方法默认请求额外获得10分钟后台时间。该方法需要传入一个代码块作为参数,如果请求获取后台执行时间失败,将会执行该代码块。该变量可作为后台任务的标识符。

    2.调用dispatch_async()方法将指定代码块提交给后台执行.

    3.后台任务执行完成时,调用UIApplication对象的endBackgroundTask:方法结束后台任务

      例如如下示例应用,该应用在系统转入后台时请求了后台执行时间,然后启动一个代码块,该代码块循环100次,模拟执行一个耗时的下载任务.从该程序转入后台的执行过程可以看出,通过这种机制即可让iOS应用在后台执行更长时间.

    下面是该应用的视图控制器类的实现部分代码

    ViewController.m

    @implementation ViewController

    - (void)viewDidLoad

    {

       [super viewDidLoad];

       // 使用默认的通知中心监听应用转入后台的过程

       //  应用转入后台时会向通知中心发送UIApplicationDidEnterBackgroundNotification

       // 从而激发enterBack:方法

       [[NSNotificationCenter defaultCenter]  addObserve:self

    selector:@selector(enterBack:)

    name:UIApplicationDidEnterBackgroundNotification

    object:[UIApplication sharedApplication]];

    }

    - (void)enterBack:(NSNotification *)notification

    {

       UIApplication *app = [UIApplication sharedApplication];

       // 定义一个UIBackgroundTaskIdentifier类型(本质就是NSUInteger)的变量

       // 该变量将作为后台任务的标识符

       __block UIBackgroundTaskIdentifier backTaskId;

       backTaskId = [app beginBackgroundTaskWithExpirationHandler:^

    {

          NSLog(@”===在额外申请的10分钟内依然没有完成任务===”);

          // 结束后台任务

         [app endBackgroundTask:backTaskId];

    }];

     if(backTaskId == UIBackgroundTaskInvalid)

    {

       NSLog(@”===iOS版本不支持后台运行,后台任务启动失败===”);

       return;

    }

    // 将代码块以异步方式提交给系统的全局并发队列

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

    , ^{

        NSLog(@”===额外申请的后台任务时间为: %f===”

    ,  app.backgroundTimeRemaining);

    // 其他内存清理的代码也可以在此处完成

    for(int i = 0 ; i < 100 ; i++)

    {

         NSLog(@”下载任务完成了%d%%” , i);// 转换成百分比

    // 暂停10秒模拟正在执行后台下载

    [NSThread sleepForTimeInterval:10];

    }

    NSLog(@”===剩余的后台任务时间为: %f===”

    ,  app.backgroundTimeRemaining);

    // 结束后台任务

    [app endBackgroundTask:backTaskId];

    });

    }

    @end

     

  • 相关阅读:
    【BZOJ】1626: [Usaco2007 Dec]Building Roads 修建道路(kruskal)
    【BZOJ】1669: [Usaco2006 Oct]Hungry Cows饥饿的奶牛(lis)
    【BZOJ】1666: [Usaco2006 Oct]Another Cow Number Game 奶牛的数字游戏(刷水严重)
    【BZOJ】1699: [Usaco2007 Jan]Balanced Lineup排队(rmq/树状数组)
    【BZOJ】1625: [Usaco2007 Dec]宝石手镯(01背包)
    【BZOJ】1617: [Usaco2008 Mar]River Crossing渡河问题(dp)
    【BZOJ】1618: [Usaco2008 Nov]Buying Hay 购买干草(dp)
    【BZOJ】1616: [Usaco2008 Mar]Cow Travelling游荡的奶牛(dp/-bfs)
    【BZOJ】1613: [Usaco2007 Jan]Running贝茜的晨练计划(dp)
    【BZOJ】1612: [Usaco2008 Jan]Cow Contest奶牛的比赛(floyd/dfs)
  • 原文地址:https://www.cnblogs.com/congli0220/p/5019945.html
Copyright © 2020-2023  润新知