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 //}