iOS 回到主线程的三种方式

作者: 奋拓达 | 来源:发表于2021-05-30 00:09 被阅读0次

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

    // 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!";
        });
    }];
    

    相关文章

      网友评论

        本文标题:iOS 回到主线程的三种方式

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