【问题标题】:"Receive canceled" when transform Publisher转换发布者时“接收取消”
【发布时间】:2021-10-06 20:39:09
【问题描述】:

我想创建一个模块,如果需要,它将刷新令牌并使用 Apple 的 Combine 重复最新请求。

目前,每个部分都运行良好,但不是这个:

  public func executeRequest<T: Decodable, E: ServerErrorType>(
    _ request: HTTPRequest,
    mapper: ObjectMapper<T, E>
  ) -> AnyPublisher<(T, HTTPResponse), Error> {
        return authentificator // <- handle refresh token stuff
          .refreshToken(force: false)
          .subscribe(on: DispatchQueue.global())
          .flatMap { token in // <- on obtain token - transform it into request

---> (here)
            session.publisher(for: request, mapper: mapper, token: token) // <- create request 
---> (here)
              .tryCatch({ error -> AnyPublisher<(T, HTTPResponse), Error> in
                if let error = error as? ServerErrorType,
                   error.isAuthError {
                  
                  return authentificator
                    .refreshToken(force: true)
                    .subscribe(on: DispatchQueue.global())
                    .flatMap { token -> AnyPublisher<(T, HTTPResponse), Error> in
                      session.publisher(for: request, mapper: mapper, token: token) //<- repeat if token refreshed
                    }
                    .eraseToAnyPublisher()
                } else {
                  throw error
                }
              })
              .print()
          }
          .receive(on: DispatchQueue.main)
          .print()
          .eraseToAnyPublisher()
   }

在令牌过期时标记(here) 的地方,tryCatch 不起作用,而是在控制台中打印“收到已取消”。我不确定我做错了什么。可以给点意见吗?

【问题讨论】:

  • 您如何订阅executeRequest?你在存储AnyCancellable 吗?另外,可能不相关,但是您需要.subscribe(on: DispatchQueue.global()) 有什么原因吗?
  • @NewDev,是的,我在 sink 之后存储可取消的,是的 - subscribe(on:) 可以省略

标签: ios swift combine urlsession


【解决方案1】:

我找到了原因 - 我的 AnyCancellable 设置变为 nil,因为 ViewModel 由于 root TabBar reinit 因为 SwiftUI 更新过程而变为 nil。 (我有一个TabBar 作为OptionalView 在另一个View 是根)

  var body: some View {
    VStack {
      switch viewModel.currentFlow {
        case .onboarding:
          WelcomeView()
            .transition(.opacity)
        case .main:
          MainTabBarView() // <- reinit here cause the issue
            .transition(.opacity)
     }
    }
  }

刷新令牌的代码完全正确,可能的修复是:

  • @StateObject 用于ViewModel
@ObservedObject private var viewModel: <MyViewModel>

更新到:

@StateObject private var viewModel: <MyViewModel>
  • 在任何重新加载时都使用 TabBar 的相同 ☝️ 实例。

可能的修复:

  private lazy let mainTabBar: MainTabBarView = .init() // <- init only once
  private lazy let welcome: WelcomeView = .init()
  
  var body: some View {
    VStack {
      switch viewModel.currentFlow {
        case .onboarding:
          welcome
            .transition(.opacity)
        case .main:
          mainTabBar
            .transition(.opacity)
      }
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多