Swift中@escaping completion handler外部访问数组为空问题
问题原因解答
- 核心原因是网络请求属于异步操作,不会阻塞当前线程的代码执行顺序,你写的代码实际执行顺序和从上到下的书写顺序并不一致:
- 进入
viewDidLoad之后首先执行fetch函数调用,dataTask被触发后会放到后台线程执行,不会等请求返回就立刻结束fetch的同步执行流程 - 接下来立刻执行你写在
fetch调用后的print(self.countriess[0].name)代码,此时网络请求还在执行,countriess还是初始化的空数组,访问下标0自然触发越界崩溃 - 等网络请求返回、数据解析完成后,你传入的
@escaping逃逸闭包才会被触发执行,这时候才会给countriess赋值,所以只有在这个闭包内部才能保证拿到有效值
- 进入
- 如果需要在其他函数中使用
countriess的数据,必须保证调用时机是在网络请求完成之后,比如可以在回调闭包赋值完成后,主动触发后续的业务逻辑或者UI刷新操作。另外要注意URLSession的回调默认运行在后台线程,如果你要操作UI,需要手动切回主线程:fetch { result in switch result { case let .failure(error): print(error) case let .success(holidays): self.countriess = holidays DispatchQueue.main.async { // 在这里执行UI刷新或者调用其他需要用到数组的方法 print(self.countriess[0].name) self.updateUI() } } }
内容的提问来源于stack exchange,提问作者PowerPlay
相关产品推荐
相关产品推荐

