我不太理解等待从任何异步调用(任何:network,timer,任何异步执行的调用,我必须等待执行另一个),并在不同的地方同步使用它(如何链接到操作。我看到使用flatmap的示例,他们引用了2个web调用。在这种情况下,我必须从web中检索数据(一个会话Id),并保存它以备将来使用(它持续一个小时)。我阅读了关于操作,DispatchGroups,我有一个简单的类,它从一个Web服务中获取数据,我必须等到它被下载,然后保存它。
import Foundation
import Combine
import CoreData
struct SessionId:Codable {
let key:String?
let dateTime:Date?
}
class ColppyModel {
var session:SessionId?
var key:String?
var cancellable:AnyCancellable?
init() {
print("saving")
let sess = SessionId(key: "1", dateTime: DateComponents(calendar:Calendar(identifier: .gregorian), year:2020, month:1, day:1).date)
guard let data = try? JSONEncoder().encode(sess) else {return}
let defaults = UserDefaults.standard
defaults.set(data, forKey: "sessionIdKey")
print("Saved \(sess)")
}
func getSessionKey(){
let requestData = ColppyAPIRequests.createSessionIdRequestData()
cancellable = ColppyAPI.sessionKeyRequest(sessionKeyJsonData: requestData)
.replaceError(with: nil)
.map{$0?.response?.data?.claveSesion}
.receive(on: DispatchQueue.global(qos: .userInteractive))
.sink(receiveValue: { (clave) in
let data = try! JSONEncoder().encode(SessionId(key: clave!, dateTime: Date()))
UserDefaults.standard.set(data, forKey: "sessionIdKey")
})
}
func getSessionIDFromUserDefaults() -> SessionId? {
let defaults = UserDefaults.standard
let data = defaults.data(forKey: "sessionIdKey")
guard let safeData = data else { return nil }
guard let sessionId = try? JSONDecoder().decode(SessionId.self, from: safeData) else {return nil}
return sessionId
}
}
我在SwiftUI View中使用它的方式是
import SwiftUI
struct ContentView: View {
let ss = ColppyModel()
var body: some View {
Text("Press")
.onTapGesture {
self.getInvoices()
}
}
private func getInvoices() {
let id = ss.getSessionIDFromUserDefaults()
print(id)
ss.getSessionKey()
print(ss.getSessionIDFromUserDefaults())
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
return ContentView()
}
}
第一次单击时,
第二次单击时,
已保存正确的项目。
如何等到从服务器检索到数据(在本例中为字符串)并保存后才能正确地从存储中获取它?
我真的不太明白合并的模式。
多谢了
1条答案
按热度按时间gmol16391#
在我看来,如果您所需要的只是在异步请求完成时做一些事情,那么在这里使用合并并没有什么真实的的好处(-您可以只使用一个常规的旧回调:
(我只是复制了您的代码,但我不建议使用
try!
)然后,您可以执行以下操作(使用尾随闭包语法)
如果你坚持使用合并,
getSessionKey
需要返回一个发布者,而不是sink
输入值。假设发布者发出一个Void
值来表示完成:现在返回一个发布者,您可以在其他地方订阅该发布者(并在那里存储可取消的发布者):
当然,现在您需要弄清楚在哪里存储可取消属性,这在不可变视图中并不容易实现(您需要将其设置为
@State
属性)。总而言之,这不是一个学习合并模式的好例子--使用回调即可。