我正在 Swift 中进行 API 调用,对此有一些疑问。 我之前经历过 JavaScript API 调用,我想将 async/await 内容添加到我的 Swift 项目中。但由于我使用的是 Swift 5,所以我还不能使用 async/await(我听说我可以从 Swift 5.5 使用它)。
我正在编写一个用于 API 调用的函数,并在我的项目中重新加载集合视图,如下代码所示。
var events = [Event]()
func populateCV() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Event>()
// What I want to do here
1. fetchEvents() // call "fetchEvents" function and get events with API request and update the events array above.
2. snapshot.appendItems(events) // append items (events array) to snapshot variable
3. collectionViewDataSource?.apply(snapshot) // reflect the changes with the new snapshot
}
func fetchEvents() {
// in this function I used Alamofire and I've got the data back (which is "result" below), and I update the events array with results array.
events = results
}
基本上,我想要做的是通过API请求结果更新事件数组,然后将更新的事件添加到快照中以更新collectionview。
由于 API 请求需要一些时间,我想等待
snapshot.appendItems(events)
和 collectionViewDataSource?.apply(snapshot)
的调用,直到 API 调用完全更新事件数组。
因此,我向 fetchEvents 添加完成并编写如下内容。
var events = [Event]()
func populateCV() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Event>()
fetchEvents {
snapshot.appendItems(self.events)
self.collectionViewDataSource?.apply(snapshot)
}
}
func fetchEvents(completion: @escaping () -> Void) {
// in this function I used Alamofire and I've got the data back (which is "result" below), and I update the events array with results array.
events = results
DispatchQueue.main.async {
completion()
}
}
它现在可以工作了,但我想知道我是否必须完成多个工作,我的代码会变得混乱。
例如,获取数据并在嵌套函数中使用数据,然后使用从上一个函数获取的数据......等等。 我想在这种情况下,我的函数会变成类似的
fetchEvents {
doTask1 {
doTask2 {
// and more...
}
}
}
那么如果我想避免那些回调地狱,我该如何在 Swift 中编写完成呢? 另外,我在第二个 fetchEvents 函数中添加了完成功能,但是是否有更简洁的代码可以使用 API 调用中新返回的数据来更新集合视图?
是的,这是在 Swift 中使用完成范例的缺点之一。毫无疑问,async/await 用起来非常棒。 如果您坚持使用完成范例,我不知道有什么办法可以解决这个问题。
您可以如何更改代码并使用 Reactiv(使用 RxSwift 或合并)范例,同时使用 Observables 包装您的完成。
例如:
fetchEvents(escaping completion: (Result<[Event]>) -> ()) {
... Alamofire and parsing code
}
将用 RxSwift 重写为
fetchEvents() -> Observalbe<[Event]> {
return Observable.create { [weak self] observer -> Disposable in
fetchEvents { events in
observer.onNext(events)
observer.onCompleted()
}
return Disposables.create()
}
}
其他功能也是如此
doTask1
和 doTask1
。
当你将它们链接起来时,它会看起来像这样
fetchEvents()
.map/flatMap/do { return doTask1 ... (rx operator if you want to map the events}
.map/flatMap/do { return doTask2 ... (rx operator if you want to map the events}
另一种选择是像 Javascript 一样使用 Promise
看看
https://github.com/mxcl/PromiseKit
,这是一个很棒的框架。
如果 PromiseKit 在您的情况下看起来像是一个开销,您可以从 John Sundell 的 this 精彩文章中获取灵感,了解如何创建自己的 Promise/Future 并将它们链接起来