已经快变成了强迫症了,看完了喜欢的东西一定要写出来,否则好像就过段时间就没有了一样。
这一章出现了很多的概念,也是iOS的特色吧,让我回想一下有哪些,哦,大概是以下这些:GCD、多线程、主线程队列获取、Block、Sleep、 UIKit 线程安全、UIActivityIndicatorView控件、实现程序在后台长久运行、NSUserDefault保存用户数据、_cmd使用等。
一、GCD--Grand Central Dispatch(中央任务调度)
这个是Apple开发的一个多核编程的解决方法。
让我们看看实例中的使用,最重要的那段:(为了简洁,就不全写了)
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{。。。。。。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
。。。。。。
});
dispatch_group_async(group, queue, ^{
。。。。。。
});
dispatch_group_notify(group, queue, ^{
。。。。。。;
dispatch_async(dispatch_get_main_queue(), ^{
。。。。。。//这里实现UIView的显示,为了UIKit线程安全,只能在主线程中实现
});
。。。。。。
});
});
详细解释一下:
^{},这种就是Block的使用,类似C#的Lamda表示方法或是C的函数指针,前面专门写了一章。
dispatch queue分成以下三种:
1)运行在主线程的Main queue,通过dispatch_get_main_queue获取。可以看出,dispatch_get_main_queue也是一种dispatch_queue_t。
2)并行队列global dispatch queue,通过dispatch_get_global_queue获取,由系统创建三个不同优先级的dispatch queue。并行队列的执行顺序与其加入队列的顺序相同。
3)串行队列serial queues一般用于按顺序同步访问,可创建任意数量的串行队列,各个串行队列之间是并发的。
当想要任务按照某一个特定的顺序执行时,串行队列是很有用的。串行队列在同一个时间只执行一个任务。我们可以使用串行队列代替锁去保护共享的数据。和锁不同,一个串行队列可以保证任务在一个可预知的顺序下执行。
serial queues通过dispatch_queue_create创建,可以使用函数dispatch_retain和dispatch_release去增加或者减少引用计数。
解释下上面的结构:dispatch_async(dispatch_get_global_queue(0,0), ^{} //后台异步执行并行队列
dispatch_group_async(group,queue, ^{} //并行执行的线程一
dispatch_group_async(group,queue, ^{} //并行执行的线程二
dispatch_group_notify(group, queue, ^{} //并行执行完后的汇总
dispatch_async(dispatch_get_main_queue(), ^{} //异步执行获取主线程队列
二、几种状态
委派方法通知名称
application:didFinishLaunchingWithOptions: UIApplicationDidFinishLaunchingNotification
applicationWillResignActive: UIApplicationWillResignActiveNotification
applicationDidBecomeActive: UIApplicationDidBecomeActiveNotification
applicationDidEnterBackground: UIApplicationDidEnterBackgroundNotification
applicationWillEnterForeground: UIApplicationWillEnterForegroundNotification
applicationWillTerminate: UIApplicationWillTerminateNotification
状态的概念是最好理解的,几种:启动、撤销活动、进入后台、进入前台、终端程序
三、让程序在后台较长久的运行
GCD的另一个用处是可以让程序在后台较长久的运行。在没有使用GCD时,当app被
按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是在使
用GCD后,app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓
存,发送统计数据等工作。利用beginBackgroundTaskWithExpirationHandler:^{}
实例中的使用方法:
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier taskId;
taskId = [app beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Background task ran out of time and was terminated.");
[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);
[NSThread sleepForTimeInterval:25];
NSLog(@"Finishing background task with %f seconds remaining",
app.backgroundTimeRemaining);
[app endBackgroundTask:taskId];
});
标准的使用方法:
// AppDelegate.h文件 @property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundUpdateTask; // AppDelegate.m文件 - (void)applicationDidEnterBackground:(UIApplication *)application { [self beingBackgroundUpdateTask]; // 在这里加上你需要长久运行的代码 [self endBackgroundUpdateTask]; } - (void)beingBackgroundUpdateTask { self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [self endBackgroundUpdateTask]; }]; } - (void)endBackgroundUpdateTask { [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask]; self.backgroundUpdateTask = UIBackgroundTaskInvalid; }
四、几种小的概念和方法
1、sleep
[NSThread sleepForTimeInterval:4];
2、活动指示器控件
UIActivityIndicatorView
3、 _cmd的使用
_cmd是iOS内置变量,始终指向当前方法的selector
4、状态加入事件通知中心
[center addObserver:self selector:@selector(applicationWillResignActive)
name:UIApplicationWillResignActiveNotification object:nil];
5、用NSUserDefault保存用户数据
使用方法:
保存:
NSInteger selectedIndex = self.segmentedControl.selectedSegmentIndex;
[[NSUserDefaults standardUserDefaults] setInteger:selectedIndex
forKey:@"selectedIndex"];
取出:
NSNumber *indexNumber = indexNumber = [[NSUserDefaults standardUserDefaults]
objectForKey:@"selectedIndex"];
if (indexNumber) {
NSInteger selectedIndex = [indexNumber intValue];
self.segmentedControl.selectedSegmentIndex = selectedIndex;}