ios开发系列之应用的后台处理

首先必须了解应用的生命周期以及执行状态,才能明白应用的后台处理

应用的生命周期

1.未运行 (Not Running):
1)应用的Info.plist包含UIApplicationExitsOnSuspend键,并且设置为YES;
2)应用之前被挂起且系统需要清除一些内存
3)应用在运行过程中崩溃

2.活跃 (Active):应用显示正常运行,并且可以接受用户输入和更新显示

3.后台(Background):用户按下Home键后不久,进入此状态.大多数将要进入Suspended状态的应用,会先短暂进入此状态.然而,对于请求需要额外的执行时间的应用,会在此状态保持更长一段时间。另外,如果一个应用要求启动时直接进入后台运行,这样的应用会直接从Not running状态进入Background状态,中途不会经过Inactive状态。

4.挂起(Suspended):挂起的应用被冻结执行,普通应用在处于后台状态后不久就会转变为此状态.当处在此状态时,应用依然驻留内存但不执行任何程序代码。当系统发生低内存告警时,系统将会将处于Suspended状态的应用清除出内存以为正在前台运行的应用提供足够的内存

5.不活跃(Inactive):应用处于其他状态之间的过渡状态,如:用户正在处理系统提示或锁定了屏幕

应用执行状态的委托方法和相应的通知名称

//    委托方法
//这是程序启动时调用的函数。可以在此方法中加入初始化相关的代码
    - (BOOL)application:didFinishLaunchingWithOptions:
//应用当前正要从前台运行状态离开时执行的函数  
 - (void)applicationWillResignActive:
//此时应用处在background状态,并且没有执行任何代码,未来将被挂起进入suspended状态    
- (void)applicationDidEnterBackground:
//当前应用正从后台移入前台运行状态,但是当前还没有到Active状态时执行的函数    
- (void)applicationWillEnterForeground:
//应用在准备进入前台运行时执行的函数。(当应用从启动到前台,或从后台转入前台都会调用此方法)    
- (void)applicationDidBecomeActive:
//当前应用即将被终止,在终止前调用的函数。如果应用当前处在suspended,此方法不会被调用    
- (void)applicationWillTerminate:
//    对应的通知名称
    UIApplicationDidFinishLaunchingNotification
    UIApplicationWillResignActiveNotification
    UIApplicationDidEnterBackgroundNotification
    UIApplicationWillEnterForegroundNotification
    UIApplicationDidBecomeActiveNotification
    UIApplicationWillTerminateNotification

1,进入后台时释放一些资源

因为系统需要为当前活跃的应用提供更多内存,任何挂起的应用都可能被终结(并返回到未运行状态),它们的内存将被释放用于其他的用途.请记住,应用处于挂起状态时所占用的资源越少,该应用被ios终止的风险就越低.通过从内存中清理那些易于重新创建的资源,可以增加应用驻留内存的机会,因此也可以大幅加快重启速度.
下面举个简单的例子:
应用进入后台状态时释放图片,然后从后台返回是重新创建它.

//1.在viewDidLoad方法中注册两个相关状态的通知
     NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
    [center addObserver:self selector:@selector(applicationDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
    [center addObserver:self selector:@selector(applicationDidEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
//2.实现这两个对应的方法
- (void)applicationDidEnterForeground{
    NSString * imagePath = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"];
    self.image = [UIImage imageWithContentsOfFile:imagePath];
    self.imageView.image = self.image;
}
- (void)applicationDidEnterBackground{ 
    self.image = nil;
    self.imageView = nil;
}

2.进入后台时保存与应用当前状态相关的信息

为了用户的最佳体验,我们希望在应用程序进入后台时,保持与用户执行操作相关的所有信息,那么用户下次回来时仍然可以恢复到他们离开时的进度.
下面举个简单的例子:
保持用户在分段控件中的选择状态为最后选择状态

//1.在viewDidLoad中创建一个UISegmentedControl对象并注册一个相关状态的通知
    self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"One",@"Two",@"Three",@"Four",@"Five"]];
    self.segmentedControl.frame = CGRectMake(bounds.origin.x + 20, 50, bounds.size.width - 40, 30);
    self.segmentedControl.selectedSegmentIndex = 0;//设置一个默认状态
    [self.view addSubview:self.segmentedControl];

    NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
    [center addObserver:self selector:@selector(applicationDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
//2.实现通知对应的方法
- (void)applicationDidEnterBackground{
    NSInteger selectedIndex = self.segmentedControl.selectedSegmentIndex;
//setObject:forKey:是单例NSUserDefaults的一个方法其中Object可以为你想保存的任何对象,  
//这个方法根据key存储某一个类的值,以便下次就可以根据key取出对应的value了
    [[NSUserDefaults standardUserDefaults] setInteger:selectedIndex forKey:@"selectedIndex"]; //进入后台保存状态
}
//3.在self.segmentedControl.selectedSegmentIndex = 0;下面添加如下代码,以恢复分段选择的索引并用于配置分段控件

//转成NSNumber 判断是否为selectedIndex键存储了值
NSNumber *indexNumber = [[NSUserDefaults standardUserDefaults] objectForKey:@"selectedIndex"];
    if (indexNumber) { //必须包含这个合理性检查
        NSInteger selectedIndex = [indexNumber intValue];
        self.segmentedControl.selectedSegmentIndex = selectedIndex;
    }

3.请求更多的后台时间

如果进入后台状态花费了太长的时间,应用可能会从内存中移除,例如你的应用可能正在进行文件传输工作,如果没能完成的话很可惜.我们要在applicationDidEnterBackground的时候,告诉系统你还有额外的工作要做.假设用户在执行其他操作时,系统仍有足够的RAM将你的应用保存在内存中,呢么系统会强制保留应用继续运行一段时间

在applicationDidEnterBackground方法中将代码修改为
    UIApplication * app = [UIApplication sharedApplication];
    __block UIBackgroundTaskIdentifier taskId;//确保该方法返回的标志符在方法创建的所有的程序块中可以共享  
//这里仅请求一个后台任务标识符,如果需要可以请求更多的标识符
    taskId = [app beginBackgroundTaskWithExpirationHandler:^{ //这个方法可以让你的应用程序在后台运行一段时间后继续运行
        [app endBackgroundTask:taskId];
    }];
    if (taskId == UIBackgroundTaskInvalid) {//表明系统没有为我们提供多余的时间
        NSLog(@"Failed to start background task!"); 
        return;
    }
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Starting background task with %f seconds remaining",app.backgroundTimeRemaining);
        //模拟一个25s的过程
        [NSThread sleepForTimeInterval:25];
        NSLog(@"Finishing background task with %f seconds remaining",app.backgroundTimeRemaining);
        //传入taskId 告诉系统我们完成了之前请求的额外时间来完成的工作 
        [app endBackgroundTask:taskId]; 
//这是对beginBackgroundTaskWithExpirationHandler方法的匹配调用,以便让系统知道我们何时完成工作
    });
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值