网络操作不能直接写在主线程中 以及 为什么不能在子线程中更新UI控件的属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络操作不能直接写在主线程中 以及 为什么不能在子线程中更新UI控件的属性相关的知识,希望对你有一定的参考价值。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //注意: 所有网络操作不能直接写在主线程中 因为所有的网络操作都是耗时的,如果加载到主线程中,会导致与用户的交互出现问题 ,所以要加载到子线程中
//    [self loadImage];
    
   [self performSelectorInBackground:@selector(loadImage) withObject:nil];

}

//加载网络图片
- (void)loadImage{
    //所有网络上的东西都是有地址的. 要获取网络数据,必须要知道这个网络数据的地址.
    NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c274c8110d0bf41bd5ad6e3928.jpg"];
    
    NSData *data = [NSData dataWithContentsOfURL:url];
    self.imageData = data;
    NSLog(@"%@",[NSThread currentThread]);
    //在子线程中直接更新UI会报错, 千万不能在子线程中更新UI (假如允许任意子线程访问、修改UI控件的属性,这就需要对多个新线程的并发访问进行同步控制,否则多个线程将会破坏UI控件内部状态的完整性)
//    self.imageView.image = [UIImage imageWithData:data];
    
//    解决方法(网络操作必须在子线程中,网络操作完成后,而更新UI操作又不能在子线程中,这里用到线程间的通信)
    //waitUntilDone : 这个参数表示是否等方法执行完成之后, 才去执行后面的代码, 一般我们写NO
    [self performSelectorOnMainThread:@selector(updateImageView) withObject:nil waitUntilDone:NO];
    
    
}
     
- (void)updateImageView{
    self.imageView.image = [UIImage imageWithData:self.imageData];
    
}

 

1.所有网络操作不能直接写在主线程中 因为所有的网络操作都是耗时的,如果加载到主线程中,会导致与用户的交互出现问题 ,所以要加载到子线程中

2.在子线程中直接更新UI会报错, 千万不能在子线程中更新UI (假如允许任意子线程访问、修改UI控件的属性,这就需要对多个新线程的并发访问进行同步控制,否则多个线程将会破坏UI控件内部状态的完整性)

3.解决方法(网络操作必须在子线程中,网络操作完成后,而更新UI操作又不能在子线程中,这里用到线程间的通信)

    //waitUntilDone : 这个参数表示是否等方法执行完成之后, 才去执行后面的代码, 一般我们写NO

 

以上是关于网络操作不能直接写在主线程中 以及 为什么不能在子线程中更新UI控件的属性的主要内容,如果未能解决你的问题,请参考以下文章

Android消息机制

Android Handler使用

为啥不能在主线程中直接捕获和处理工作线程抛出的异常?

关于Handler的理解,子线程不能更新UI的纠正和回调的思考

Android——消息分发机制

android.os.NetworkOnMainThreadException 在4.0之后谷歌强制要求连接网络不能在主线程进行访问