简单说将代码同步到主线程执行的三种方法如下:
// 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!";
});
以下代码有什么问题?如何修复?
@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;
}
这段代码是想提醒用户等待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!";
}
NSOperationQueue级主线程同步:[NSOperationQueue mainQueue]
NSOperationQueue *waitQueue = [[NSOperationQueue alloc] init];
[waitQueue addOperationWithBlock:^{
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
// 同步到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.alert.text = @"Thanks!";
}];
}];
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!";
});
}];
网友评论