遍历Publisher合并框架

时间:2019-10-25 18:32:33

标签: swift combine

我具有以下功能来执行URL请求:

final class ServiceManagerImpl: ServiceManager, ObservableObject {
    private let session = URLSession.shared

    func performRequest<T>(_ request: T) -> AnyPublisher<String?, APIError> where T : Request {
        session.dataTaskPublisher(for: self.urlRequest(request))
            .tryMap { data, response in
                try self.validateResponse(response)
                return String(data: data, encoding: .utf8)
            }
            .mapError { error in
                return self.transformError(error)
            }
            .eraseToAnyPublisher()
    }
}

具有以下两个功能,我现在可以从对应的 ViewModel 调用所需的请求:

final class AuditServiceImpl: AuditService {
    private let serviceManager: ServiceManager = ServiceManagerImpl()

    func emptyAction() -> AnyPublisher<String?, APIError> {
        let request = AuditRequest(act: "", nonce: String.randomNumberGenerator)
        return serviceManager.performRequest(request)
    }

    func burbleAction(offset: Int) -> AnyPublisher<String?, APIError> {
        let request = AuditRequest(act: "burble", nonce: String.randomNumberGenerator, offset: offset)
        return serviceManager.performRequest(request)
    }
}
final class AuditViewModel: ObservableObject {
    @Published var auditLog: String = ""
    private let auditService: AuditService = AuditServiceImpl()

    init() {
        let timer = Timer(timeInterval: 5, repeats: true) { _ in
            self.getBurbles()
        }
        RunLoop.main.add(timer, forMode: .common)
    }

    func getBurbles() {
        auditService.emptyAction()
            .flatMap { [unowned self] offset -> AnyPublisher<String?, APIError> in
                let currentOffset = Int(offset?.unwrapped ?? "") ?? 0
                return self.auditService.burbleAction(offset: currentOffset)
            }
            .receive(on: RunLoop.main)
            .sink(receiveCompletion: { [unowned self] completion in
                print(completion)
            }, receiveValue: { [weak self] burbles in
                self?.auditLog = burbles!
            })
            .store(in: &cancellableSet)
    }
}

当我第一次使用self.getBurbles()时,一切都很好。但是,对于接下来的调用,print(completion)显示finished,并且代码不执行self?.auditLog = burbles!

我不知道如何遍历getBurbles()函数并获得不同间隔的响应。

修改

整个过程简而言之:

  • 我从类初始化程序调用{​​{1}}
  • getBurbles()调用2个嵌套函数:getBurbles()emptyAction()
  • 这2个函数生成不同的请求并调用burbleAction(offset: Int)
  • 最后,我将响应设置为performRequest<T>(_ request: T)变量,并将其显示在 SwiftUI 层上

1 个答案:

答案 0 :(得分:1)

这里至少有2个问题。

首先,当for row in range(row_start, row_end+1): for column in range(column_start, column_end+1): print(lst[row,column]) 错误时,它将不再产生元素。这是一个问题,因为即使内部Publisher失败,您也想在这里回收发布者并多次调用它。您需要处理Publisher内部的错误,并确保该错误不会传播到封闭的flatMap。 (即,您可以返回Publisher或其他一些Result或元组,指示您应该显示错误状态。)

第二,enum几乎肯定不是您想要的,因为它将合并所有api调用并以任意顺序返回它们。如果要取消任何现有请求并仅显示最新结果,则应使用flatMap,然后使用switchToLatest