1 // 2 // ViewController.m 3 // nsthreaddemo 4 // 5 // Created by ys on 15/11/23. 6 // Copyright (c) 2015年 ys. All rights reserved. 7 // 8 //需求分析 9 // 10 //1. UIImageView显示图片 11 //2. UIImage模拟从网络上下载 12 //3. NSString记录图片路径 13 #import "ViewController.h" 14 15 @interface ViewController () 16 17 @property (nonatomic, strong) UIImageView *imageView; 18 @property (nonatomic, strong) UIImage *image; 19 @property (nonatomic, strong) NSString *imagePath; 20 21 @end 22 23 @implementation ViewController 24 25 // 0. 模拟使用图像路径加载图片 26 - (void)setImagePath:(NSString *)imagePath 27 { 28 @autoreleasepool { 29 NSLog(@"%@", [NSThread currentThread]); 30 31 // 1> 模拟下载,延时 32 [NSThread sleepForTimeInterval:1.0]; 33 34 // 2> 设置图像,苹果底层允许使用performSelectorInBackground方法 35 // 在后台线程更新UI,强烈不建议大家这么做! 36 // YES会阻塞住线程,直到调用方法完成 37 // NO不会阻塞线程,会继续执行 38 [self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageNamed:imagePath] waitUntilDone:NO]; 39 } 40 } 41 42 // 1. 图像 43 - (void)setImage:(UIImage *)image 44 { 45 46 self.imageView.image = image; 47 48 // [NSThread sleepForTimeInterval:1.0]; 49 // 根据图片自动调整大小 50 [self.imageView sizeToFit]; 51 } 52 53 // 2. 创建imageView 54 - (UIImageView *)imageView 55 { 56 if (!_imageView) { 57 _imageView = [[UIImageView alloc] init]; 58 } 59 60 return _imageView; 61 } 62 63 64 - (void)viewDidLoad { 65 [super viewDidLoad]; 66 [self.view addSubview:self.imageView]; 67 68 // 在后台线程执行这段代码即可 69 for (int i = 0; i < 50; ++i) { //打印线程会发现新建了大量线程 70 [self performSelectorInBackground:@selector(setImagePath:) withObject:@"头像1.png"]; 71 } 72 } 73 74 // 75 //小结 76 // 77 //方法,看起来很简单, 78 // 79 //1> 不能够自动回收线程,如果并发数量多,会建立大量的子线程! 80 //2> 使用NSThread的线程,不会自动添加autoreleasepool 81 // 82 //意味着,如果在后台线程方法中, 83 // 84 // 85 //主线程中是有自动释放池的,使用GCD和NSOperation也会自动添加自动释放池 86 // 87 //NSThread和NSObject不会,如果在后台线程中创建了autorelease的对象,需要使用自动释放池,否则会出现内存泄漏! 88 // 89 //@autoreleasepool {} 自动释放池 90 //工作原理: 91 // 92 //1. 当自动释放池被销毁或者“耗尽”时,对池中的所有对象发送release消息,清空自动释放池 93 //2. 所有autorelease的对象,在出了作用域之后,会自动添加到【最近一次创建的自动释放池中】自动释放池中 94 // 95 //在ARC中,编译器在编译过程中,会自动根据代码结构,添加retain和release。 96 @end 97 98 //- (void)demo 99 //{100 // // 提问:代码存在什么问题?如果循环次数非常大,会出现什么问题?应该如何修改?101 // 102 // // 解决办法1:如果i比较大,可以在for循环外添加自动释放池103 // // 解决方法2:如果i玩命大,一次循环都会造成自动释放池被填满,可以在for循环内添加自动释放池104 // for (int i = 0; i < 10000000; ++i) {105 // @autoreleasepool {106 // // *107 // NSString *str = @"Hello World!";108 // // new *109 // str = [str uppercaseString];110 // // new *111 // str = [NSString stringWithFormat:@"%@ %d", str, i];112 // 113 // NSLog(@"%@", str);114 // }115 // }116 //}