iOS 后台线程

首先介绍一下iOS应用运行过程中会经历的5种状态:

Not Running:非运行状态

Inactive:前台非活动状态

Active:前台活动状态

Background:后台状态

Suspended:挂起状态


在应用状态迁移过程中回调的方法有以下几种:

application:didFinishLaunchingWithOptions:应用启动并进行初始化时

applicationDidBecomeActive:应用进入前台并处于活动状态时

applicationWillResignActive:应用从活动状态进入到非活动状态时

applicationDidEnterBackground:应用进入后台时

applicationWillEnterForeground:应用进入到前台,但还没有处于活动状态时

applicationWillTerminate:应用被终止时

本文主要描述应用的后台运行。当应用在前台运行时,点击Home键,根据应用属性文件中的Application does not run in background的值(Yes/No),此时该应用将分两种情况执行,经历的状态也有一点区别。

(1) 应用可以在后台运行

Active   -->  Inactive  -->  Background  -->  Suspended

(2) 应用不可以在后台运行

Active -->  Inactive  -->  Background  -->  Suspended  -->  Not Running


我们知道,应用进入后台时,会调用applicationDidEnterBackground:方法,注意:不要在 applicationDidEnterBackground: 方法中执行耗时较长的任务,否则iOS系统可能直接从内存中删除该应用。另外,对于多线程任务,当应用进入后台时,如果该任务还没有执行完成,应用进入后台时该任务会被暂停。


为了请求更多的后台运行时间,可以调用 UIApplication 对象的 beginBackgroundTaskWithExpiration Handler: 方法。

首先使用默认通知中心监听UIApplicationDidEnterBackgroundNotification(应用进入后台通知),然后调用enterBack:方法。

- (void)viewDidLoad
{
    [super viewDidLoad];
	// 使用默认通知中心监听应用转入后台的过程
	// 应用转入后台时会向通知中心发送UIApplicationDidEnterBackgroundNotification
	// 从而激发enterBack:方法
	[[NSNotificationCenter defaultCenter] addObserver:self
		selector:@selector(enterBack:)
		name:UIApplicationDidEnterBackgroundNotification
		object:[UIApplication sharedApplication]];
}

然后在enterBack:方法中调用 UIApplication 对象的 beginBackgroundTaskWithExpiration Handler: 方法获取更多的后台运行时间,并调用 dispatch_async() 方法将指定代码块(需要在后台执行的任务)提交给后台执行,后台任务完成或超时后都要调用 UIApplication 对象的 endBackgroundTask: 方法来结束后台任务。

- (void) enterBack:(NSNotification*)notification
{
	UIApplication* app = [UIApplication sharedApplication];
	// 定义一个UIBackgroundTaskIdentifier类型(本质就是NSUInteger)的变量,
	// 该变量将作为后台任务的标示符
	__block UIBackgroundTaskIdentifier backTaskId;
    /* beginBackgroundTaskWithExpirationHandler: 方法默认请求额外获取10分钟的后台时间 */
	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:1];
			}
			NSLog(@"===剩余的后台任务时间为:%f==="
				  , app.backgroundTimeRemaining);
			// 结束后台任务
			[app endBackgroundTask:backTaskId];
		});
}

通过 beginBackgroundTaskWithExpirationHandler: 方法来请求更多的后台运行时间,当该应用的后台时间减少到0时,将会调用 handler 代码块。
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler

如果该应用不能在后台执行,则会返回 UIBackgroundTaskInvalid否则会返回后台任务的标识符,然后将该标识符传给

- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier 方法,用来结束任务。






你可能感兴趣的:(移动开发)