Tip
- 1.UIImageView延遲加載照片
- 2.線程保活
- 3.子線程中執(zhí)行NSTimer
- 4.performSelector
- 5.自動(dòng)釋放池
一.UIImageView延遲加載照片
在實(shí)際的開(kāi)發(fā)過(guò)程中和面試題中,我們總?cè)フf(shuō)可以在tableview的滑動(dòng)的時(shí)候不去加載照片尤蒿,因?yàn)殇秩究赡軙?huì)阻塞主線程教馆,我們總說(shuō):可以再tableview停止滑動(dòng)的時(shí)候再去渲染照片,現(xiàn)在可以好好聊聊這個(gè)話題
//控制中寫(xiě)上這個(gè)方法即可,3秒鐘然后顯示照片
//這個(gè)方法,我看就可以在滑動(dòng)的時(shí)候,延遲顯示照片
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.imageview performSelector:@selector(setImage:)
withObject:[UIImage imageNamed:@"123.png"]
afterDelay:3];
}
//這個(gè)是第二種清空颅崩,然后直接指定什么模式,二者等價(jià)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.imageview performSelector:@selector(setImage:)
withObject:[UIImage imageNamed:@"123.png"]
afterDelay:3
inModes:@[NSDefaultRunLoopMode]];
}
- 如果想讓照片的顯示或者timer的運(yùn)行在任何時(shí)候都好使怎么辦?
設(shè)置為commonMode就行了
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self.imageview performSelector:@selector(setImage:)
withObject:[UIImage imageNamed:@"123.png"]
afterDelay:3
inModes:@[NSRunLoopCommonModes]];
}
二.線程鼻迫幔活
可能你的項(xiàng)目中需要一個(gè)線程漆弄,一直在后臺(tái)做些耗時(shí)操作,但是不影響主線程造锅,我們不要一直大量的創(chuàng)建和銷毀線程撼唾,因?yàn)檫@樣太浪費(fèi)性能了,我們只要保留這個(gè)線程哥蔚,只要對(duì)他進(jìn)行“钡构龋活”就行
//繼承了一個(gè)NSTread 線程蛛蒙,然后使用vc中創(chuàng)建和執(zhí)行某個(gè)任務(wù),查看線程的情況
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
WXThread *thread = [[WXThread alloc] initWithTarget:self
selector:@selector(doSomeThing)
object:nil];
[thread start];
}
- (void)doSomeThing{
NSLog(@"doSomeThing");
}
//每一次點(diǎn)擊屏幕的時(shí)候恨锚,線程執(zhí)行完方法宇驾,直接釋放掉了,下一次創(chuàng)建了一個(gè)新的線程猴伶;
//子線程存活的時(shí)間很短,只要執(zhí)行完畢任務(wù)塌西,就會(huì)被釋放
2017-04-19 16:03:10.686 WXAllTest[14928:325108] doSomeThing
2017-04-19 16:03:10.688 WXAllTest[14928:325108] WXTread - dealloc - <WXThread: 0x600000276780>{number = 3, name = (null)}
2017-04-19 16:03:18.247 WXAllTest[14928:325194] doSomeThing
2017-04-19 16:03:18.249 WXAllTest[14928:325194] WXTread - dealloc - <WXThread: 0x608000271340>{number = 4, name = (null)}
2017-04-19 16:03:23.780 WXAllTest[14928:325236] doSomeThing
2017-04-19 16:03:23.781 WXAllTest[14928:325236] WXTread - dealloc - <WXThread: 0x608000270e00>{number = 5, name = (null)}
如果我每隔一段時(shí)間就像在線程中執(zhí)行某個(gè)操作他挎,好像現(xiàn)在不行
如果我們將線程對(duì)象強(qiáng)引用,也是不行的捡需,會(huì)崩潰
1.成為基本屬性
/** 線程對(duì)象 */
@property(strong,nonatomic) WXThread *thread;
2.創(chuàng)建線程之后办桨,直接將入到RunLoop中
- (void)viewDidLoad {
[super viewDidLoad];
_thread = [[WXThread alloc] initWithTarget:self
selector:@selector(doSomeThing)
object:nil];
[_thread start];
}
3.執(zhí)行doSomeThing函數(shù)
- (void)doSomeThing{
//一定要加入一個(gè)timer,port站辉,或者是obervers呢撞,否則RunLoop啟動(dòng)不起來(lái)
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
}
4.在點(diǎn)擊屏幕的時(shí)候,執(zhí)行一個(gè)方法饰剥,線程之間的數(shù)據(jù)通信
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self performSelector:@selector(test) onThread:_thread withObject:nil waitUntilDone:NO modes:@[NSDefaultRunLoopMode]];
}
5.將test方法寫(xiě)清楚
- (void)test{
NSLog(@"current thread - %@",[NSThread currentThread]);
}
//打印結(jié)果:同一個(gè)線程殊霞,線程保活成功
2017-04-19 18:21:07.660 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
2017-04-19 18:21:07.843 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
2017-04-19 18:21:08.015 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
2017-04-19 18:21:08.194 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
2017-04-19 18:21:08.398 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
2017-04-19 18:21:08.598 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
2017-04-19 18:21:08.770 WXAllTest[16145:382366] current thread - <WXThread: 0x60800007c180>{number = 3, name = (null)}
三.子線程中執(zhí)行NSTimer
剛才學(xué)習(xí)了在RunLoop中去處理源,source (seletor)汰蓉,現(xiàn)在來(lái)看看如何在子線程中處理NSTimer
/** 線程對(duì)象 */
@property(strong,nonatomic) WXThread *thread;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//延遲圖片加載
_thread = [[WXThread alloc] initWithTarget:self
selector:@selector(execute)
object:nil];
[_thread start];
}
- (void)execute{
//該方法默認(rèn)不加入RunLoop中绷蹲,使用schedule可以
NSTimer *timer = [NSTimer timerWithTimeInterval:0.3
target:self
selector:@selector(test2)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
}
- (void)test2{
NSLog(@"current thread ********** 2 - %@",[NSThread currentThread]);
}
//打印:
2017-04-19 18:45:18.342 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:18.643 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:18.943 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:19.243 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:19.544 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:19.842 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:20.143 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:20.443 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:20.743 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:21.042 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
2017-04-19 18:45:21.342 WXAllTest[16508:398383] current thread ********** 2 - <WXThread: 0x608000261380>{number = 3, name = (null)}
注意: 這兩者相同,后者默認(rèn)直接創(chuàng)建了RunLoop顾孽,然后加進(jìn)去了祝钢,但是一定要run才能啟動(dòng),但是過(guò)去我們沒(méi)有在主線程中run若厚,也好使啊拦英,為毛?因?yàn)樵谥骶€程中系統(tǒng)自動(dòng)run了,否則線程早就停止了
NSTimer *timer = [NSTimer timerWithTimeInterval:0.3
target:self
selector:@selector(test2)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(test2)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] run];
因?yàn)閠extView是主線程的乞封,而timer是子線程的東西做裙,所以沒(méi)關(guān)系
五.自動(dòng)釋放池
1.什么是自動(dòng)釋放池,就是將目前使用到的對(duì)象放到池子中肃晚,然后當(dāng)自動(dòng)釋放池銷毀的時(shí)候锚贱,對(duì)內(nèi)部的所有對(duì)象都進(jìn)行realese操作,retrainCount減一
2.自動(dòng)釋放池什么時(shí)候銷毀和創(chuàng)建关串?
當(dāng)每一次要進(jìn)入睡眠狀態(tài)拧廊,那么就會(huì)銷毀监徘,當(dāng)即將醒來(lái)的時(shí)候,重新創(chuàng)建
一個(gè)RunLoop對(duì)應(yīng)一個(gè)線程
建議每一次啟動(dòng)RunLoop的時(shí)候吧碾,包裝一個(gè)自動(dòng)釋放池凰盔,臨時(shí)創(chuàng)建了很多對(duì)象,等著我們釋放倦春,在很多優(yōu)秀的開(kāi)源庫(kù)中户敬,都有這個(gè)說(shuō)明
- (void)viewDidLoad {
[super viewDidLoad];
//延遲圖片加載
_thread = [[WXThread alloc] initWithTarget:self
selector:@selector(execute)
object:nil];
[_thread start];
}
- (void)execute{
// 該方法默認(rèn)不加入RunLoop中,使用schedule可以
@autoreleasepool {
NSTimer *timer = [NSTimer timerWithTimeInterval:0.3
target:self
selector:@selector(test2)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
}
}