复习时看的:
最大并发数 异步执行 同一个时间开启的线程数量
NSOperationQueue 需要掌握 默认都是 dispatch_get_global_queue()全局队列(并发的) [NSOperationQueue mainQueue]主队列(同步 没有并发 不开新线程)
queue.maxConcurrentOperationCount = 3
dispatch_after NSOperationQueue添加NSBlockOperation将operation变成block 相当于dispatch_async(queue,block)
【这个了解
NSBlockOperation 添加block [op start] 第一个block不开新线程 第二个开始开新线程 setCompletion 相当于在最后一个block执行完毕后在里面追加一个方法
[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download:) object:nil] start]; //当前线程执行 所以价值不大
】
queue cancelAllOperations; 内存警告的时候调用一下 不可恢复
[queue setSuspended:YES]; //对性能要求很高的情况下 一般不用 发现用户滚动tableView暂时暂停下载操作
[queue setSuspended:NO];//恢复队列中的任务
-------------------
0916 线程 单例 操作
- (void)delay1
{
// 延迟执行不要用sleep,坏处:卡住当前线程
[NSThread sleepForTimeInterval:3];
NSLog(@"-----下载图片-----");
}
- (void)delay2
{
// 不会卡主当前线程
[self performSelector:@selector(download:) withObject:@"http://555.jpg" afterDelay:3];
}
- (void)delay3
{
// 3秒后回到主线程执行block中的代码 不卡当前线程
// dispatch_queue_t queue = dispatch_get_main_queue();
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
// NSLog(@"------task------%@", [NSThread currentThread]);
// });
// 开启新线程 执行block中的代码 不卡当前线程
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"------task------%@", [NSThread currentThread]);
});
}
----
只要是 某个类的实例 只执行一次
【调用后 这个类对应的方法区 会将这个dispatch_once抹去 保证了无论多少个对象实例 都只有执行一次的机会 可以用于只允许下载一次的操作】
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"----touchesBegan");
static dispatch_once_t onceToken; //自动生成的
dispatch_once(&onceToken, ^{
NSLog(@"----once");
HMImageDownloader *downloader = [[HMImageDownloader alloc] init];
[downloader download];
});
}
-----------
了解即可
队列组(2个队列放到一个组里 2个队列都执行完了 才执行dispatch_group_notify)(了解)
同时下载2张图片 dispatch_group_notify回到主线程显示UI
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 1.队列组
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.下载图片1
__block UIImage *image1 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data1 = [NSData dataWithContentsOfURL:url1];
image1 = [UIImage imageWithData:data1];
});
// 3.下载图片2
__block UIImage *image2 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
NSData *data2 = [NSData dataWithContentsOfURL:url2];
image2 = [UIImage imageWithData:data2];
});
// 4.合并图片 (保证执行完组里面的所有任务之后,再执行notify函数里面的block)
dispatch_group_notify(group, queue, ^{
// 开启一个位图上下文
UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
// 绘制第1张图片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
// 绘制第2张图片
CGFloat image2W = image2.size.width * 0.5;
CGFloat image2H = image2.size.height * 0.5;
CGFloat image2Y = image1H - image2H;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的图片
UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
// 5.回到主线程显示图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = fullImage;
});
});
}
--------
ARC变非ARC环境
1、
2、开启僵尸对象检测
----------
--------------
单例模式
+(void)load类加载的时候调用
+(void)initialize 当类第一次干活时调用
+(void)load类加载的时候调用 +(void)initialize 当类第一次干活时调用 对象要实现 [obj copy] 需要实现 <NSCopint>协议 可以不用写<NSCoping> 因为这个只是方便敲出代码用的 如果定义全局变量 id _musicTool; 其他类里面也可以随意访问 extern id _musicTool; 应该 static id _musicTool 这样就只允许 MusicTool类对 _musicTool变量进行访问
懒汉式(推荐 面试经常问)
// HMMusicTool.m // 03-单例模式-Singleton(掌握) // 懒汉式 #import "HMMusicTool.h" @implementation HMMusicTool static id _instance; /** * alloc方法内部会调用这个方法 */ + (id)allocWithZone:(struct _NSZone *)zone { if (_instance == nil) { // 防止频繁加锁 @synchronized(self) { if (_instance == nil) { // 防止创建多次 _instance = [super allocWithZone:zone]; } } } return _instance; } + (instancetype)sharedMusicTool { if (_instance == nil) { // 防止频繁加锁 @synchronized(self) { if (_instance == nil) { // 防止创建多次 _instance = [[self alloc] init]; } } } return _instance; } - (id)copyWithZone:(NSZone *)zone { return _instance; } @end
饿汉式(了解即可 不需要掌握)
// HMSoundTool.m // 03-单例模式-Singleton // 饿汉式 #import "HMSoundTool.h" @implementation HMSoundTool static id _instance; /** * 当类加载到OC运行时环境中(内存),就会调用一次(一个类只会加载1次) */ + (void)load { _instance = [[self alloc] init]; } + (id)allocWithZone:(struct _NSZone *)zone { if (_instance == nil) { // 防止创建多次 _instance = [super allocWithZone:zone]; } return _instance; } + (instancetype)sharedSoundTool { return _instance; } - (id)copyWithZone:(NSZone *)zone { return _instance; } ///** // * 当第一次使用这个类的时候才会调用 // */ //+ (void)initialize //{ // NSLog(@"HMSoundTool---initialize"); //} @end
-
代理抽取成宏 放到pch文件中
----
----------------------
ARC 非ARC 代码适配
-----------------
基于GCD(系统会根据cpu来决定开多少个 一般4~5个就不开了 同一时间 不要看num等于几)的NSOperation抽象类 常用
子类继承NSOperation实现内部方法
将操作放到 NSOperation抽像类的子类 对象中 子类对象放到NSOperationQuere中 系统自动取出NSQquere中的NSOeration子类对象a,并将a中的方法开启新线程执行
--------------
NSBlockOperation 由于
第一个任务用主线程
第二个开始 都新增线程
最后setCompletionBlock采用最后一个执行完毕的线程
a操作完成 后执行 异步
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1---%@",[NSThread currentThread]); //主线程 }]; [op setCompletionBlock:^{ // 新开的thread2 异步 NSLog(@"3-----%@",[NSThread currentThread]); }]; [op start];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1---%@",[NSThread currentThread]); //主线程 }]; [op addExecutionBlock:^{ //开启一个新线程 thread2 异步 NSLog(@"2----%@",[NSThread currentThread]); }]; [op setCompletionBlock:^{ // 等待最后一个thread执行 完毕 采用最后一个线程来执行 NSLog(@"3-----%@",[NSThread currentThread]); }]; [op start];//第一个是主线程 第二个 第三个是 新开的线程
NSBlockOperation中任务大于等于2的时候会开启新线程 等于1的时候只开启一个当前线程 主线程
--------------
最大并发数 异步执行 同一个时间开启的线程数量
NSOperationQueue 需要掌握 默认都是 dispatch_get_global_queue()全局队列(并发的) [NSOperationQueue mainQueue]主队列(同步 没有并发 不开新线程)
maxConcurrentOperationCount = 3 很重要 最大新开多少个线程数 设置为1就是1个新线程串行 设置为3就是3个新线程并发
------
使用NSOperationQueue是为了限制某个operation不能开新线程 operation里再加几个block也没用 这里operation变成一个Block了
如果在operation1 addExcutionBlock 也不会新增线程数量了
最简单的异步执行方法 queue里添加几个就开几个新线程
这个比GCD更简单 是对GCD的封装
--------------
这个了解即可
[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download:) object:nil] start]; //当前线程执行 所以价值不大
如果放到NSOperationQueue中,会自动开新线程 异步执行
-----
依赖操作
------
C依赖A C依赖B 就是 C操作在a后面 C操作在B后面
这样就实现了 等a下载图片 b下载图片都操作完了 再执行C合并图片操作
-----
不同队列中的操作也可以依赖
-----------
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ // 1.异步下载图片 NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; // 2.回到主线程,显示图片 // [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>]; // dispatch_async(dispatch_get_main_queue(), ^{ // // }); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image; }]; }]; }
---------------
queue cancelAllOperations; 内存警告的时候调用一下 不可恢复
[queue setSuspended:YES]; //对性能要求很高的情况下 一般不用 发现用户滚动tableView暂时暂停下载操作
[queue setSuspended:NO];//恢复队列中的任务
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // [queue cancelAllOperations]; // 取消队列中的所有任务(不可恢复) } -(void)didReceiveMemoryWarning1 { [super didReceiveMemoryWarning]; // [queue cancelAllOperations]; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // [queue setSuspended:YES]; // 暂停队列中的所有任务 // [queue setSuspended:YES];//暂停 } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // [queue setSuspended:NO]; // 恢复队列中的所有任务 // [queue setSuspended:NO]; }
----------------------------------
其他:
单例(宏的方式)代码找到放到微云里