PerformSelector 相關(guān)
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
這三個(gè)方法是同步在當(dāng)前線程執(zhí)行的。會(huì)阻塞當(dāng)前線程』踉幔可在主線程或者子線程執(zhí)行垢粮。
比如
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelector:@selector(doSomething:) withObject:@"111"];
NSLog(@"over");
}
- (void)doSomething:(NSString *)aStr {
NSLog(@"doSomething:__%@__, currentThread = %@", aStr, [NSThread currentThread]);
sleep(2);
NSLog(@"doSomething sleep over");
}
打印結(jié)果是
doSomething:__111__, currentThread = <NSThread: 0x7fe18c904ac0>{number = 1, name = main}
(2s later...)
doSomething sleep over
over
如果在子線程里做會(huì)立即打印 over贴届。子線程嘛,當(dāng)然不會(huì)阻塞主線程蜡吧。
PerformSelector:afterDelay 相關(guān)
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSString *> *)modes;
這兩個(gè)方法類(lèi)似毫蚓,只是第二個(gè)方法里指定了線程中 Runloop 的 Modes,這個(gè)先不說(shuō)昔善。
這個(gè)方法是異步的元潘,而且只能在主線程中執(zhí)行。什么意思呢君仆?
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelector:@selector(doSomething:) withObject:@"ahahaha" afterDelay:0];
NSLog(@"before sleep");
sleep(4);
NSLog(@"after sleep");
}
- (void)doSomething:(NSString *)aStr {
NSLog(@"doSomething:__%@__, currentThread = %@", aStr, [NSThread currentThread]);
}
打印結(jié)果是
before sleep
(4s later...)
after sleep
doSomething:__ahahaha__, currentThread = <NSThread: 0x7fdf73706c70>{number = 1, name = main}
能看出來(lái)翩概,這個(gè)方法不會(huì)阻塞當(dāng)前線程,而是把 Selector 加到主隊(duì)列里返咱,當(dāng) delay 之后執(zhí)行 Selector钥庇。如果主線程在執(zhí)行業(yè)務(wù),那只能等到執(zhí)行完所有業(yè)務(wù)之后才會(huì)去執(zhí)行 Selector咖摹,就算 delay 等于 0评姨。
那 delay 從什么時(shí)候開(kāi)始計(jì)算呢?從 performSelector 的時(shí)候萤晴。就算這時(shí)主線程在阻塞也會(huì)計(jì)算時(shí)間吐句,當(dāng)阻塞結(jié)束之后,如果到了 delay 那就執(zhí)行 Selector店读,如果沒(méi)到就繼續(xù) delay嗦枢。
PerformSelectorOnMainThread 相關(guān)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
// 相關(guān)的指定線程方法就不提了。一個(gè)意思屯断。
這倆方法意思很明確文虏,可以在主或者子線程中執(zhí)行,但 Selector 肯定是在主線程中執(zhí)行裹纳。這里只提一下 waitUntilDone择葡。
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelectorOnMainThread:@selector(doSomething:) withObject:@"1111" waitUntilDone:YES];
NSLog(@"before sleep");
sleep(2);
NSLog(@"after sleep");
}
- (void)doSomething:(NSString *)aStr {
NSLog(@"doSomething:__%@__, currentThread = %@", aStr, [NSThread currentThread]);
sleep(2);
NSLog(@"doSomething sleep over");
}
打印結(jié)果是
doSomething:__1111__, currentThread = <NSThread: 0x7fc90b5038b0>{number = 1, name = main}
(2s later...)
doSomething sleep over
before sleep
(2s later);
after sleep
很明顯,waitUntilDone == YES 會(huì)阻塞當(dāng)前線程剃氧,當(dāng)主線程執(zhí)行完 Selector 之后才會(huì)繼續(xù)執(zhí)行當(dāng)前線程敏储。如果是 NO 呢?
before sleep
(2s later...)
after sleep
doSomething:__1111__, currentThread = <NSThread: 0x7fc90b5038b0>{number = 1, name = main}
(2s later);
doSomething sleep over
主線程不會(huì)阻塞當(dāng)前線程朋鞍,大家互不干擾已添。但上述代碼中的當(dāng)前線程是主線程妥箕,那么和 performSelector:afterDelay 類(lèi)似,主線程順序執(zhí)行完業(yè)務(wù)之后才會(huì)繼續(xù)執(zhí)行 Selector 的業(yè)務(wù)更舞。如果當(dāng)前線程是子線程呢畦幢?
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t t1 = dispatch_queue_create("sub queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(t1, ^{
[self performSelectorOnMainThread:@selector(doSomething:) withObject:@"1111" waitUntilDone:NO];
NSLog(@"before sleep");
sleep(2);
NSLog(@"after sleep");
});
}
- (void)doSomething:(NSString *)aStr {
NSLog(@"doSomething:__%@__, currentThread = %@", aStr, [NSThread currentThread]);
sleep(2);
NSLog(@"doSomething sleep over");
}
打印結(jié)果是
before sleep
doSomething:__1111__, currentThread = <NSThread: 0x7ff7c2603a00>{number = 1, name = main}
(after 2s...)
after sleep
doSomething sleep over
當(dāng)前線程和主線程互不干擾,大家是并行的缆蝉。那如果 waitUntilDone == YES 呢宇葱?
當(dāng)然是等主線程執(zhí)行完之后再接著執(zhí)行子線程里的業(yè)務(wù)了。
doSomething:__1111__, currentThread = <NSThread: 0x7fd3a1f03510>{number = 1, name = main}
(2s later...)
doSomething sleep over
before sleep
(2s later...)
after sleep
大致就是這樣刊头。