http://blog.csdn.net/cordova/article/details/54933729
簡單說將代碼同步到主線程執行的三種方法如下:// 1.NSThread
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
- (void)updateUI {
// UI更新代碼
self.alert.text = @"Thanks!";
}
// 2.NSOperationQueue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// UI更新代碼
self.alert.text = @"Thanks!";
}];
// 3.GCD
dispatch_async(dispatch_get_main_queue(), ^{
// UI更新代碼
self.alert.text = @"Thanks!";
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
看下面的例子:
以下代碼有什麼問題?如何修復?
@interface TTWaitController : UIViewController
@property (strong, nonatomic) UILabel *alert;
@end
@implementation TTWaitController
- (void)viewDidLoad
{
CGRect frame = CGRectMake(20, 200, 200, 20);
self.alert = [[UILabel alloc] initWithFrame:frame];
self.alert.text = @"Please wait 10 seconds...";
self.alert.textColor = [UIColor whiteColor];
[self.view addSubview:self.alert];
NSOperationQueue *waitQueue = [[NSOperationQueue alloc] init];
[waitQueue addOperationWithBlock:^{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
self.alert.text = @"Thanks!";
}];
}
@end
@implementation TTAppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = [[TTWaitController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
這段代碼是想提醒用戶等待10s,10s後在標籤上顯示“Thanks”,但多線程代碼部分NSOperationQueue的addOperationWithBlock函數不能保證block裏面的語句是在主線程中運行的,UILabel顯示文字屬於UI更新,必須要在主線程進行,否則會有未知的操作,無法在界面上及時正常顯示。
解決方法是將UI更新的代碼寫在主線程上即可,代碼同步到主線程上主要有三種方法:NSThread、NSOperationQueue和GCD,三個層次的多線程都可以獲取主線程並同步。
NSThread級主線程同步:performSelectorOnMainThread
NSOperationQueue *waitQueue = [[NSOperationQueue alloc] init];
[waitQueue addOperationWithBlock:^{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
// 同步到主線程
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];
}];
/**
* UI更新函數
*/
- (void)updateUI {
self.alert.text = @"Thanks!";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
NSOperationQueue級主線程同步:[NSOperationQueue mainQueue]
NSOperationQueue *waitQueue = [[NSOperationQueue alloc] init];
[waitQueue addOperationWithBlock:^{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
// 同步到主線程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.alert.text = @"Thanks!";
}];
}];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
GCD級主線程同步:dispatch_get_main_queue
NSOperationQueue *waitQueue = [[NSOperationQueue alloc] init];
[waitQueue addOperationWithBlock:^{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
// 同步到主線程
dispatch_async(dispatch_get_main_queue(), ^{
self.alert.text = @"Thanks!";
});
}];