美文网首页selectoriOSiOS开发文集
iOS子线程更新UI到主线程的三种方法

iOS子线程更新UI到主线程的三种方法

作者: 街角仰望 | 来源:发表于2018-03-30 16:58 被阅读507次

代码同步到主线程执行的三种方法如下:

// 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:10]];
    // 同步到主线程
    dispatch_async(dispatch_get_main_queue(), ^{
        self.alert.text = @"Thanks!";
    });
}];

参考:https://blog.csdn.net/cordova/article/details/54933729

相关文章

  • iOS常用知识点总结一

    1、iOS子线程更新UI到主线程的三种方法 2、给self.view画一个类似self.layer.border的...

  • 子线程更新UI的方法

    子线程中不能直接更新UI,如果直接更新的话会发生崩溃所以要在主线程中更新UI,总计三种回到主线程更新UI的方式 1...

  • Android消息机制 Handler

    在Android中解决子线程更新UI的三种方法: Activity中 调用 runOnUiThread(Runna...

  • 工作线程转换为UI线程三种方式

    我们将工作线程转换为UI线程,主要是进行UI的更新操作;在工作线程中使用三种方法: Activity的runOnU...

  • Android多线程

    1.沿用java的子线程创建 2.在子线程中不能更新UI,那么在Android中更新UI的方法 runOnUiTh...

  • Android Handler

    Hander机制,将子线程需要更新UI操作信息传递到主线程,从而实现UI更新。 基本写法: ``` Handler...

  • Android: 线程相关知识点

    快速切换到主线程更新UI的三种方法 Activity.runOnUiThread(Runnable)把更新UI的代...

  • 线程通讯详解

    关于子线程能否更新UI的思考线程通讯详解线程池-多线程的高效使用姿势 上文我们说到了关于子线程中能否更新UI的问题...

  • APP崩溃提示:This application is modi

    崩溃输出日志 崩溃原因 在子线程中更新UI导致主线程的视图布局出错 解决方法 把更新UI的操作放在主线程中执行 s...

  • 如何做到在子线程更新 UI?

    一般来讲,子线程是不能更新 UI 的,如果在子线程更新 UI,会报错。 但在某种情况下直接开启线程更新 UI 是不...

网友评论

    本文标题:iOS子线程更新UI到主线程的三种方法

    本文链接:https://www.haomeiwen.com/subject/shalcftx.html