多线程技术(三)
2016-05-20 20:00
162 查看
[Demo01_GCD_plist]
TRTableViewController.m
TRTableViewCell.m
TRAlbum.h
TRDataManager.m
[Demo02_GCD_SDWebImage]
TRTableViewController.m
[Demo03_Group]
[Demo04_Singleton]
DataManager.h
DataManager.m
TRTableViewController.m
<span style="font-size:14px;">#import "TRTableViewController.h" #import "TRDataManager.h" #import "TRAlbum.h" #import "TRTableViewCell.h" @interface TRTableViewController () @property (nonatomic, strong) NSArray *albumsArray; //存储下载好的图片的数据 @property (nonatomic, strong) NSMutableDictionary *imageMutableDic; @end @implementation TRTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.albumsArray = [TRDataManager getAllAlbums]; //初始化可变字典 self.imageMutableDic = [NSMutableDictionary dictionary]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.albumsArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TRTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"albumCell"]; // Configure the cell... //singer/name //数据源 TRAlbum *album = self.albumsArray[indexPath.row]; cell.textLabel.text = album.singer; cell.detailTextLabel.text = album.name; //赋值一个占位图片(两个lable不会最左边排列) cell.imageView.image = [UIImage imageNamed:@"s0"]; //实现图片缓存的原理 //判断字典中有没有 NSData *readData = self.imageMutableDic[album.poster]; if (readData) { //字典中有图片数据;显示 cell.imageView.image = [UIImage imageWithData:readData]; } else { //字典中没有;判断沙盒中有没有 NSString *filePath = [self generateFilePath:album.poster]; NSData *dataFromFile = [NSData dataWithContentsOfFile:filePath]; if (dataFromFile) { //沙盒中有图片数据;显示 cell.imageView.image = [UIImage imageWithData:dataFromFile]; } else { //字典没有;沙盒没有;开始下载图片 [self downloadImageWithCell:cell withAlbum:album]; } } //下载图片 // [self downloadImageWithCell:cell withAlbum:album]; return cell; } - (void)downloadImageWithCell:(TRTableViewCell *)cell withAlbum:(TRAlbum *)album { dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURL *imageURL = [NSURL URLWithString:album.poster]; NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; if (imageData) { //存到字典中 self.imageMutableDic[album.poster] = imageData; //存到沙盒文件中(文件所在的整个路径) NSString *filePath = [self generateFilePath:album.poster]; [imageData writeToFile:filePath atomically:YES]; } //返回主线程更新 dispatch_async(dispatch_get_main_queue(), ^{ cell.imageView.image = [UIImage imageWithData:imageData]; // //刷新 // [self.tableView reloadData]; }); }); } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 80; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // NSLog(@"dfafdsagagdg"); } //返回已经拼接好的文件的路径 - (NSString *)generateFilePath:(NSString *)imageURLStr { //找Caches路径 NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; //获取url最后一部分:s2874587.jpg //https://img1.doubanio.com/mpic/s2874587.jpg NSString *imageName = [imageURLStr lastPathComponent]; return [cachesPath stringByAppendingPathComponent:imageName]; } </span>
TRTableViewCell.m
<span style="font-size:14px;">- (void)setSelected:(BOOL)selected animated:(BOOL)animated { //当点击cell的时候,会自动触发这个方法;父类自动的重新设置cell的imageView的frame // [super setSelected:selected animated:animated]; //自定义cell选中的颜色 if (selected) { //选中的颜色 [self setBackgroundColor:[UIColor colorWithRed:245.0/255 green:245.0/255 blue:245.0/255 alpha:1]]; } else { //默认颜色 [self setBackgroundColor:[UIColor whiteColor]]; } }</span>
TRAlbum.h
<span style="font-size:14px;">/** 歌曲名字 */ @property (nonatomic, copy) NSString *name; /** 歌手名字 */ @property (nonatomic, copy) NSString *singer; /** 专辑图片URL */ @property (nonatomic, copy) NSString *poster;</span>
TRDataManager.m
<span style="font-size:14px;">static NSArray *_albumsArray = nil;//只从文件中读一次 + (NSArray *)getAllAlbums { if (!_albumsArray) { _albumsArray = [[self alloc] getAllAlbums]; } return _albumsArray; } - (NSArray *)getAllAlbums { //plist路径 NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"albums.plist" ofType:nil]; //取plist数据 NSArray *plistArray = [NSArray arrayWithContentsOfFile:plistPath]; //for循环将字典转成TRAlbum NSMutableArray *mutableArray = [NSMutableArray array]; for (NSDictionary *albumDic in plistArray) { //NSDictionary -> Album TRAlbum *album = [TRAlbum new]; [album setValuesForKeysWithDictionary:albumDic]; [mutableArray addObject:album]; } return [mutableArray copy]; } </span>
[Demo02_GCD_SDWebImage]
TRTableViewController.m
<span style="font-size:14px;">static void *imageViewFrameKey = &imageViewFrameKey; - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TRTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"albumCell"]; // Configure the cell... //singer/name //数据源 TRAlbum *album = self.albumsArray[indexPath.row]; cell.textLabel.text = album.singer; cell.detailTextLabel.text = album.name; //赋值一个占位图片(两个lable不会最左边排列) // cell.imageView.image = [UIImage imageNamed:@"s0"]; //使用KVO方式监听cell的frame变化 [cell.imageView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:imageViewFrameKey]; //实现图片缓存的原理 [cell.imageView sd_setImageWithURL:[NSURL URLWithString:album.poster] placeholderImage:[UIImage imageNamed:@"s0"]]; return cell; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == imageViewFrameKey) { NSLog(@"====%@", change[@"new"]); //此时监听到imageView的frame发生变化,改成自定义的frame值 UIImageView *imageView = (UIImageView *)object; CGRect newRect = CGRectMake(20, 9, 60, 60); if (!CGRectEqualToRect(imageView.frame, newRect)) { imageView.frame = newRect; } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } </span>
[Demo03_Group]
<span style="font-size:14px;">// 1.创建一个group组对象 dispatch_group_t group = dispatch_group_create(); // 2.添加两个任务(5s; 8s);全局队列+异步执行 dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{ //子线程执行 NSLog(@"下载图片一开始"); [NSThread sleepForTimeInterval:5]; NSLog(@"下载图片一结束"); }); dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{ NSLog(@"下载图片二开始"); [NSThread sleepForTimeInterval:8]; NSLog(@"下载图片二结束"); }); // 3.GCD中通知的方法,告诉两个任务完毕 dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{ //子线程 NSLog(@"两个图片下载完毕,上传开始..."); //回到主线程 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"开始更新新界面..."); }); }); </span>
[Demo04_Singleton]
<span style="font-size:14px;">//调用线程不安全单例方法 //需求:使用shared方法和使用alloc两种方法返回的对象都是同一个(更加严格单例方式) //调用线程安全的严格的单例方法 //shared+alloc+copy TRDataManager *firstDataManager = [TRDataManager sharedDataManagerBySafe]; TRDataManager *secondDataManager = [[TRDataManager alloc] init]; TRDataManager *thirdDataManager = [secondDataManager copy]; NSLog(@"first:%p; second:%p; third:%p", firstDataManager, secondDataManager, thirdDataManager); </span>
DataManager.h
<span style="font-size:14px;">//返回单例对象,使用线程不安全方式 + (instancetype)sharedDataManagerByUnsafe; //返回单例对象,使用线程安全方式(GCD一次性任务) + (instancetype)sharedDataManagerBySafe;</span>
DataManager.m
<span style="font-size:14px;">static DataManager *_dataManagerByUnsafe = nil; + (instancetype)sharedDataManagerByUnsafe { if (!_dataManagerByUnsafe) { _dataManagerByUnsafe = [[DataManager alloc] init]; } return _dataManagerByUnsafe; } //////////////////////////////////// static DataManager *_dataManagerBySafe = nil; + (instancetype)sharedDataManagerBySafe { //1.创建一个静态的一次性任务对象 static dispatch_once_t onceToken; //2.调用一次性任务方法 dispatch_once(&onceToken, ^{ //创建单例对象 _dataManagerBySafe = [[DataManager alloc] init]; }); //3.返回单例对象 return _dataManagerBySafe; } //重写alloc方法; 或者重写allocWithZone + (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _dataManagerBySafe = [super allocWithZone:zone]; }); return _dataManagerBySafe; } //当copy当前类型对象时候,返回唯一的单例对象 - (id)copyWithZone:(NSZone *)zone { return _dataManagerBySafe; } ////////////////////////////// //创建单例的方式三 static DataManager *_dataManagerByInit = nil; + (void)initialize { if (self == [DataManager class]) { //初始化操作;一定能保证只调用一次+线程安全的 _dataManagerByInit = [[DataManager alloc] init]; } } + (instancetype)sharedDataManagerByInit { return _dataManagerByInit; } </span>
相关文章推荐
- 【bzoj 2393】Cirno的完美算数教室
- HashMap和HashSet的区别
- 字典树典型应用(1247)
- const char **ptr 与 char *ptr[] 的释放问题的探究
- MySQL入门--显示指定数据表的字段结构、插入指定字段的值(记录)、查看指定表中指定字段的所有记录
- 索尼Z2(L50t)刷CM12教程
- BZOJ 4553: [Tjoi2016&Heoi2016]序列
- 从Eclipse转移到IntelliJ IDEA的一点心得
- 用c++实现单向链表和双向链表
- Office10安装提示:Microsoft Office 2010 安装要求您的计算机上安装 MSXML 版本 6.10.1129.0
- 图像配准】基于灰度的模板匹配算法(一):MAD、SAD、SSD、MSD、NCC、SSDA、SATD算法
- Android之ListView优化基本
- Linux_2_Navigation
- 内容模式
- querySelectorAll对象无ID的题
- Wolf and Rabbit (hdu_1222) 欧几里德
- 【IPC通信】有名管道FIFO
- [No000097]程序员面试题集【下】
- django ajax 应用实例
- java代码中发送http请求的DnsResolver使用问题