Swift - 使用来自异步方法的数据更新视图
Swift - Updating the view with data from an async method
我是 swift 的新手,正在使用异步代码。
我有一个方法可以从 API 中获取数据,将数据放入对象并将这些对象放入数组中。然后我想用数组中那些对象的数据更新 UI 。
为了说明 UI 正在更新,我将更改标签的值。
因为从 API 获取信息的方法是异步的,所以我无法 return 从中获取值。相反,我传递了一个回调:
@IBOutlet var labelTest: UILabel!
private var eventsArray : Array<Event> = Array<Event>()
override func viewDidLoad() {
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
})
sleep(5) //this is of course not good, but I'll leave it here to illustrate what's going on.
self.labelTest.text = eventsArray[0].description
}
这 有效 因为让线程休眠会留出时间来填充数组。然而,让主线程休眠是一个非常糟糕的主意,并且不能保证数据会在这段时间内 returned。
如果 sleep(...)
被删除,那么 UI 标签会在 getEventsFromAPI
调用完成之前尝试更新,从而产生运行时错误(因为数组仍然是无)。
尝试 2:
@IBOutlet var labelTest: UILabel!
private var eventsArray : Array<Event> = Array<Event>()
override func viewDidLoad() {
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
self.labelTest.text = eventsArray[0].description
})
}
在尝试 #2 中,我正在从后台线程更新 UI,这并不好并会产生以下警告:
This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.
那么,在 getEventsFromAPI
调用完成后,有什么方法可以从主线程更新 UI (即更改标签文本)(这样数组实例变量现在就不是无)?
你快到了。最后的技巧是从主线程调用 UI 更新:
override func viewDidLoad() {
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
// Update the UI on the main thread
DispatchQueue.main.async {
self.labelTest.text = eventsArray[0].description
}
})
}
在Swift4中,这个可以做得更简单一点:
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
// Update the UI on the main thread
DispatchQueue.main.async() {
self.labelTest.text = eventsArray[0].description
}
})
我是 swift 的新手,正在使用异步代码。
我有一个方法可以从 API 中获取数据,将数据放入对象并将这些对象放入数组中。然后我想用数组中那些对象的数据更新 UI 。
为了说明 UI 正在更新,我将更改标签的值。
因为从 API 获取信息的方法是异步的,所以我无法 return 从中获取值。相反,我传递了一个回调:
@IBOutlet var labelTest: UILabel!
private var eventsArray : Array<Event> = Array<Event>()
override func viewDidLoad() {
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
})
sleep(5) //this is of course not good, but I'll leave it here to illustrate what's going on.
self.labelTest.text = eventsArray[0].description
}
这 有效 因为让线程休眠会留出时间来填充数组。然而,让主线程休眠是一个非常糟糕的主意,并且不能保证数据会在这段时间内 returned。
如果 sleep(...)
被删除,那么 UI 标签会在 getEventsFromAPI
调用完成之前尝试更新,从而产生运行时错误(因为数组仍然是无)。
尝试 2:
@IBOutlet var labelTest: UILabel!
private var eventsArray : Array<Event> = Array<Event>()
override func viewDidLoad() {
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
self.labelTest.text = eventsArray[0].description
})
}
在尝试 #2 中,我正在从后台线程更新 UI,这并不好并会产生以下警告:
This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.
那么,在 getEventsFromAPI
调用完成后,有什么方法可以从主线程更新 UI (即更改标签文本)(这样数组实例变量现在就不是无)?
你快到了。最后的技巧是从主线程调用 UI 更新:
override func viewDidLoad() {
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
// Update the UI on the main thread
DispatchQueue.main.async {
self.labelTest.text = eventsArray[0].description
}
})
}
在Swift4中,这个可以做得更简单一点:
APIAccessUtil.getEventsFromAPI({(eventsList: Array<Event>) -> Void in
self.eventsArray = eventsList
// Update the UI on the main thread
DispatchQueue.main.async() {
self.labelTest.text = eventsArray[0].description
}
})