多线程2
- GCD队列组:
- 基本使用:
//0.创建队列组
dispatch_group_t group = dispatch_group_create();
//1.创建队列
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
//2.添加任务
//dispatch_async:1)封装任务&2)提交任务到队列
//dispatch_group_async:1)封装任务&2)提交任务到队列&3)把当前的任务的执行情况纳入到队列组的监听范围中
dispatch_group_async(group,queue, ^{
NSLog(@"download1---%@",[NSThread currentThread]);
});
- 常用函数
// 两者配合使用,后面的异步任务被监听
dispatch_group_enter(group);
dispatch_group_leave(group);
// 当队列中的任务执行完后执行block
dispatch_group_notify(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, <#^(void)block#>)
// 一直到前面的代码块都执行完,下面的代码块才执行
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
- 队列和组队列的区别
- 队列:封装任务,添加任务到队列
- 组队列:封装任务,添加任务到队列,添加队列到组
- 单例模式设计:
- 设计分析:
//1.静态变量
static XMGTool *_instance;
//2.重写分配空间的方法(alloc会重写allocWithZone方法)
//alloc --->allocWithZone
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
//解决安全问题
/*
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
*/
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
//3.提供类方法
+(instancetype)shareXMGTool
{
return [[self alloc]init];
}
//4.严谨
-(id)copyWithZone:(NSZone *)zone
{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
NSOpreation认识学习:
-
使用方法:
- NSInvocationOperation方法:
1.封装操作 NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download1) object:nil]; 2.开始操作 [op1 start];
- NSBlockOperation方法:
//1.封装操作 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1---%@",[NSThread currentThread]); }]; //追加操作 //如果操作里面的任务数量大于一,那么会开子线程一起执行 [op3 addExecutionBlock:^{ NSLog(@"4---%@",[NSThread currentThread]); }]; //2.开始操作 [op1 start];
- 自定义NSOpreation子类
多图下载案例总结:
项目设计思路:框架搭建(XMGApp存放模型数据)->解决图片重复下载问题(内存缓存->磁盘缓存)->界面运行卡顿问题解决(将图片下载等耗时操作放到子线程中)->队列重复创建问题(懒加载队列)->数据错乱问题解决(将每次下载的任务都添加到内存中,并在下一次下载的时候检查内存是否有相应任务)->图片不显示问题解决(刷新每个cell)->cell重复使用(清空设置完的图片或者设置占位图片)
框架搭建:省略
-
图片重复下载问题解决:
1.检查内存缓存中的图片,并往内存缓存中设置图片 UIImage *image = [self.images objectForKey:appM.icon]; [self.images setObject:image forKey:appM.icon]; 2.检查磁盘缓存中的图片,并往磁盘缓存中设置图片 NSString *cachesPath =[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; //得到图片的名称 NSString *filename = [appM.icon lastPathComponent]; //拼接文件的全路径 NSString *fullPath = [cachesPath stringByAppendingPathComponent:filename]; //去检查磁盘缓存 NSData *data = [NSData dataWithContentsOfFile:fullPath]; //把图片保存到磁盘缓存(图片不能直接写入file中,需要变为二进制数据) [data writeToFile:fullPath atomically:YES];
界面运行卡顿问题解决:
```objc
将下载任务放到子线程中
NSBlockOperation dowbloadOperation = [NSBlockOperation blockOperationWithBlock:^{
......
}];
[self.queue addOperation:dowbloadOperation];
```
- 队列重复创建问题解决:
```objc
-(NSOperationQueue *)queue
{
if (_queue == nil) {
_queue = [[NSOperationQueue alloc]init];
_queue.maxConcurrentOperationCount = 5;
}
return _queue;
}
```
- 数据错乱问题解决:
1.懒加载任务字典,存放任务
-(NSMutableDictionary *)operations
{
if (_operations == nil) {
_operations = [NSMutableDictionary dictionary];
}
return _operations;
}
2.检查操作缓存
NSBlockOperation *dowbloadOperation = [self.operations objectForKey:appM.icon];
3.添加操作到缓存中
[self.operations setObject:dowbloadOperation forKey:appM.icon];
- 图片不显示问题解决:
```objc
//设置图片([tableView reloadData];刷新整个tableView cell.imageView.image = image;storyboard中的cell中imageView尺寸默认为0)
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
//刷新指定的行
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationMiddle];
}];
```
- cell复用问题解决:
```objc
//清空图片或者是设置占位图片
cell.imageView.image = [UIImage imageNamed:@"Snip20200808_172"];
```
- 项目运行报错(超时或找不到图片):
if (image == nil) {
//把操作从操作缓存中移除
[self.operations removeObjectForKey:appM.icon];
return ;
}
- 内存警告问题解决:
-(void)didReceiveMemoryWarning
{
//移除内存缓存
[self.images removeAllObjects];
//取消队列中的操作
[self.queue cancelAllOperations];
}