美文网首页
iOS中的网络和多线程编程(四)

iOS中的网络和多线程编程(四)

作者: anny_4243 | 来源:发表于2022-02-17 09:53 被阅读0次

摘自《iOS程序员面试笔试宝典》

UIKit类要在哪一个应用线程上使用

UIKit的界面类只能在主线程上使用,对界面进行更新,多线程环境中要对界面进行更新必须要切换到主线程上。

例如下面的问题代码:

@interface TTWaitController ()

@property (strong, nonatomic) UILabel *alert;

@end

@implementation TTWaitController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    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;
}

@end

这段代码是想提醒用户等待10s,10s后在标签上显示“Thanks”,但多线程代码部分NSOperationQueue的addOperationWithBlock函数不能保证block里面的语句是在主线程中运行的,UILabel显示文字属于UI更新,必须要在主线程进行,否则会有未知的操作,无法在界面上及时正常显示。

解决方法是将UI更新的代码写在主线程上。代码同步到主线程上主要有3种方法:NSThread、NSOperationQueue和GCD,3个层次的多线程都可以获取主线程并同步。

iOS中有哪几种从其他线程回到主线程的方法

iOS中只有主线程才能立即刷新UI。如果是通过侦听异步消息,触发回调函数,或者调用异步方法,请求刷新UI,那么都会产生线程阻塞和延迟的问题。如果要在其他线程中执行刷新UI的操作,那么就必须切换回主线程。主要由以下3种方式。

1.NSThreadPerformAdditions协议

这个协议提供了两个切换到主线程的API。

-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

2.GCD

使用GCD的dispatch_get_main_queue()方法可以获取主队列,主队列中的任务必定是在主线程中执行的。

dispatch_async(dispatch_get_main_queue(), ^{        
});

3.NSOperationQueue

和GCD一样,使用NSOperationQueue提供+mainQueue方法可以获取主队列,再将刷新UI的任务添加到主队列中。

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];

示例代码如下:

- (void)goToMainThread{
    /*开启子线程下载图片*/
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSData *imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:@"http://jxh1992.com/pe0060886.jpg"]];
        _image = [UIImage imageWithData:imageData];
        /*切换到主线程显示*/
        //1.NSThread
//        [self performSelectorOnMainThread:@selector(changeBe) withObject:nil waitUntilDone:NO];
        //2.GCD
//        dispatch_async(dispatch_get_main_queue(), ^{
//            [self changeBe];
//        });
        //3.NSOperationQueue
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            [self changeBe];
        }];
    });
}

相关文章

网友评论

      本文标题:iOS中的网络和多线程编程(四)

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