【发布时间】:2020-05-09 19:55:54
【问题描述】:
我正在尝试使用 Combine 来执行 POST 请求。在执行我之前使用的 http 请求时,我的 Credentials 对象返回状态码 200,一切都很好。但是当我尝试使用 Combine 框架时,它只会返回一个错误。
finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled"
如何解决此问题以使我的组合 POST 请求按预期工作?
我的合并请求不起作用,需要修复:
func demoLogin() -> AnyPublisher<Credentials, Error> {
let url = URL(string: "https://web-api/auth/create-demo-account")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
return URLSession.shared
.dataTaskPublisher(for: urlRequest)
.receive(on: DispatchQueue.main)
.map(\.data)
.decode(
type: Credentials.self,
decoder: JSONDecoder())
.eraseToAnyPublisher()
}
所以这就是我下沉价值的地方:
final class OnboardingViewModel: ObservableObject {
private var subscriptions = Set<AnyCancellable>()
func demoLogin() {
AuthRequest.shared.demoLogin()
.sink(
receiveCompletion: { print($0) },
receiveValue: {
print("Receive value:\nLogin: \($0.login)\nToken: \($0.token)") })
.store(in: &subscriptions)
}
}
这是按钮请求调用的 SwiftUI 视图:
struct CredentialsButtons: View {
@ObservedObject var viewModel = OnboardingViewModel()
var body: some View {
VStack {
Button(action: { self.viewModel.demoLogin() }) {
Text("Try demo")
.font(.subheadline)
.fontWeight(.medium)
.foregroundColor(.blue)
}
}
}
}
我的请求正常工作:
func demoLogin(completion: @escaping (NetworkResult<Credentials>) -> Void) {
let url = URL(string: "https://web-api/auth/create-demo-account")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
let dataTask = authSession.dataTask(with: urlRequest) { data, response, error in
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200,
let jsonData = data else {
completion(.failure)
return
}
do {
let credentials = try JSONDecoder().decode(Credentials.self, from: jsonData)
completion(.success(credentials))
}
catch {
completion(.failure)
}
}
dataTask.resume()
}
【问题讨论】:
-
也许您正在订阅
.sink而没有保存它返回的AnyCancellable。向我们展示调用demoLogin并订阅发布者的代码。 -
我刚刚添加了我订阅发布者的代码作为帖子更新。
-
您的
OnboardingViewModel是ObservableObject,但它没有Published属性,否则会发送objectWillUpdate信号。你如何创建和存储它? -
在存储任何内容之前,我只想在控制台中查看我的值是否返回正确的状态代码。这就是为什么在我的 .sink 中打印的原因。否则,我只需以这种方式在按钮中调用此函数:viewModel.demoLogin()
-
谁持有
OnboardingViewModel,能否添加调用viewModel.demoLogin()的代码?
标签: swift httprequest combine