本文首發在個人我的博客: blog.shenyuanluo.com,喜歡的朋友歡迎訂閱。html
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
withObject:nil];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,3,4
performSelector:withObject:
會在當前線程當即執行指定的 selector 方法。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
withObject:nil
afterDelay:0];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,4
performSelector:withObject:afterDelay:
實際是往 RunLoop 裏面註冊一個定時器,而在子線程中,RunLoop 是沒有開啓(默認)的,全部不會輸出 3
。官網 API 做以下解釋:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
withObject:nil
afterDelay:0];
[[NSRunLoop currentRunLoop] run];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,3,4
[[NSRunLoop currentRunLoop] run];
會建立的當前子線程對應的 RunLoop 對象並啓動了,所以能夠執行 test
方法;而且 test
執行完後,RunLoop 中註冊的定時器已經無效,因此還能夠輸出 4
(對比 例子⑥例子)。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:YES];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,3,4
performSelector:onThread:withObject:waitUntilDone:
會在指定的線程執行,而執行的策略根據參數 wait
處理,這裏傳 YES
代表將會當即阻斷 指定的線程 並執行指定的 selector
。官網 API 解釋以下:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,4
performSelector:onThread:withObject:waitUntilDone:
會在指定的線程執行,而執行的策略根據參數 wait
處理,這裏傳 NO
代表不會當即阻斷 指定的線程 而是將 selector
添加到指定線程的 RunLoop 中等待時機執行。(該例子中,子線程 RunLoop 沒有啓動,全部沒有輸出 3
)官網 API 解釋以下:- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
[[NSRunLoop currentRunLoop] run];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,3
[[NSRunLoop currentRunLoop] run];
已經建立的當前子線程對應的 RunLoop 對象並啓動了,所以能夠執行 test
方法;可是 test
方法執行完後,RunLoop 並無結束(使用這種啓動方式,RunLoop 會一直運行下去,在此期間會處理來自輸入源的數據,而且會在 NSDefaultRunLoopMode
模式下重複調用 runMode:beforeDate:
方法)因此沒法繼續輸出 4
。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,3
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
已經建立的當前子線程對應的 RunLoop 對象並啓動了,所以能夠執行 test
方法;可是 test
方法執行完後,RunLoop 並無結束(使用這種啓動方式,能夠設置超時時間,在超時時間到達以前,runloop會一直運行,在此期間runloop會處理來自輸入源的數據,而且會在 NSDefaultRunLoopMode
模式下重複調用 runMode:beforeDate:
方法)因此沒法繼續輸出 4
。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
複製代碼
1,2,3,4
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
已經建立的當前子線程對應的 RunLoop 對象並啓動了,所以能夠執行 test
方法;並且 test
方法執行完後,RunLoop 馬上結束(使用這種啓動方式 ,RunLoop 會運行一次,超時時間到達或者第一個 input source
被處理,則 RunLoop 就會退出)因此能夠繼續輸出 4
。- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
複製代碼
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
複製代碼
- (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;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;
複製代碼
- (void)run;
啓動,RunLoop 會一直運行下去,在此期間會處理來自輸入源的數據,而且會在 NSDefaultRunLoopMode
模式下重複調用 runMode:beforeDate:
方法;- (void)runUntilDate:(NSDate *)limitDate;
啓動,能夠設置超時時間,在超時時間到達以前,RunLoop 會一直運行,在此期間 RunLoop 會處理來自輸入源的數據,而且也會在 NSDefaultRunLoopMode
模式下重複調用 runMode:beforeDate:
方法;- (void)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;
啓動,RunLoop 會運行一次,超時時間到達或者第一個 input source
被處理,則 RunLoop 就會退出。