您的位置:首页 > 移动开发 > IOS开发

iOS-----后台运行

2015-12-04 17:15 260 查看

后台运行

当应用程序进入后台时,系统会自动回调应用程序委托的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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: