【问题标题】:Why is my Combine httpMethod post request not working?为什么我的组合 httpMethod 发布请求不起作用?
【发布时间】: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 并订阅发布者的代码。
  • 我刚刚添加了我订阅发布者的代码作为帖子更新。
  • 您的OnboardingViewModelObservableObject,但它没有Published 属性,否则会发送objectWillUpdate 信号。你如何创建和存储它?
  • 在存储任何内容之前,我只想在控制台中查看我的值是否返回正确的状态代码。这就是为什么在我的 .sink 中打印的原因。否则,我只需以这种方式在按钮中调用此函数:viewModel.demoLogin()
  • 谁持有OnboardingViewModel,能否添加调用viewModel.demoLogin()的代码?

标签: swift httprequest combine


【解决方案1】:

这不是一个有效的 URL。按如下方式将印刷品插入您的出版商,以便您查看错误:

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)
    .print()
    .decode(
      type: Credentials.self,
      decoder: JSONDecoder())
    .eraseToAnyPublisher()
}

一旦你让它返回有效数据,你就可以在解码后移动打印以报告和解码错误。

【讨论】:

  • 当然那个URL是无效的,我没有在StackOverflow上添加真实的。该问题已解决,因为该错误是由在 SwiftUI 视图中与 @State 变量同时调用 demoLogin() 引起的。当我更改已发布变量的状态时,一切都按预期工作。
【解决方案2】:

网络调用按预期工作。在我调用 demoLogin() ViewModel 方法的按钮中找到了导致此错误的代码。问题是我不能在 ViewModel 网络调用的同时调用 @State 变量。

发送错误的按钮:

Button(action: {
  withAnimation {
    self.viewModel.demoLogin()
    self.isLoggedIn.toggle()
    self.enterDemoMode.toggle() }
}) {
  Text("Try demo")
    .font(.subheadline)
    .fontWeight(.medium)
    .foregroundColor(.blue)
}

通过将 SwiftUI 视图的 @State 变量替换为我的 ViewModel 中的 @Published 变量并在 demoLogin() 中而不是在 SwiftUI 视图按钮中调用它们来修复错误。

Button(action: {
  withAnimation {
    self.viewModel.demoLogin() } // Fixed
}) {
  Text("Try demo")
    .font(.subheadline)
    .fontWeight(.medium)
    .foregroundColor(.blue)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-09
    • 2013-12-20
    • 2021-10-05
    • 2019-10-26
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多