gpt4 book ai didi

swift - 实现与 URLSession 发布者和组合的重新连接

转载 作者:行者123 更新时间:2023-12-04 19:57:37 55 4
gpt4 key购买 nike

我想知道是否有办法使用新的 Apple 框架实现重新连接机制结合和使用 URLSession 发布者

  • 试图在 WWDC 2019
  • 中找到一些示例
  • 试图玩waitsForConnectivity没有运气(它甚至没有在自定义 session 中调用委托(delegate))
  • 试过URLSession.background但它在发布过程中崩溃了。

  • 我也不明白我们如何以这种方式跟踪进度
    有没有人已经尝试过这样做?

    更新:
    好像是 waitsForConnectivity is not working在 Xcode 11 测试版中

    更新2:
    Xcode 11 通用 - waitsForConnectivity正在工作,但 仅限 在设备上。使用默认 session ,设置标志并实现 session 委托(delegate)。方法 task is waiting for connectivity无论您是否使用带有回调的初始化任务,都将被调用。
    public class DriverService: NSObject, ObservableObject {

    public var decoder = JSONDecoder()
    public private(set) var isOnline = CurrentValueSubject<Bool, Never>(true)

    private var subs = Set<AnyCancellable>()
    private var base: URLComponents
    private lazy var session: URLSession = {
    let config = URLSessionConfiguration.default
    config.waitsForConnectivity = true
    return URLSession(configuration: config, delegate: self, delegateQueue: nil)
    }()

    public init(host: String, port: Int) {

    base = URLComponents()
    base.scheme = "http"
    base.host = host
    base.port = port

    super.init()

    // Simulate online/offline state
    //
    // let pub = Timer.publish(every: 3.0, on: .current, in: .default)
    // pub.sink { _ in
    // let rnd = Int.random(in: 0...1)
    // self.isOnline.send(rnd == 1)
    // }.store(in: &subs)
    // pub.connect()
    }

    public func publisher<T>(for driverRequest: Request<T>) -> AnyPublisher<T, Error> {

    var components = base
    components.path = driverRequest.path

    var request = URLRequest(url: components.url!)
    request.httpMethod = driverRequest.method

    return Future<(data: Data, response: URLResponse), Error> { (complete) in
    let task = self.session.dataTask(with: request) { (data, response, error) in
    if let err = error {
    complete(.failure(err))
    } else {
    complete(.success((data!, response!)))
    }
    self.isOnline.send(true)
    }
    task.resume()
    }
    .map({ $0.data })
    .decode(type: T.self, decoder: decoder)
    .eraseToAnyPublisher()
    }
    }

    extension DriverService: URLSessionTaskDelegate {

    public func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) {
    self.isOnline.send(false)
    }

    }

    最佳答案

    你试过retry(_:)然而?可在 Publisher 上获得s 并在失败时重新运行请求。

    如果您不希望所有失败的请求立即重新运行,那么您可以使用 catch(_:)并决定哪些故障需要重新运行。

    这里有一些代码来实现取得进展。

    enum Either<Left, Right> {
    case left(Left)
    case right(Right)

    var left: Left? {
    switch self {
    case let .left(value):
    return value
    case .right:
    return nil
    }
    }

    var right: Right? {
    switch self {
    case let .right(value):
    return value
    case .left:
    return nil
    }
    }
    }

    extension URLSession {
    func dataTaskPublisherWithProgress(for url: URL) -> AnyPublisher<Either<Progress, (data: Data, response: URLResponse)>, URLError> {
    typealias TaskEither = Either<Progress, (data: Data, response: URLResponse)>
    let completion = PassthroughSubject<(data: Data, response: URLResponse), URLError>()
    let task = dataTask(with: url) { data, response, error in
    if let data = data, let response = response {
    completion.send((data, response))
    completion.send(completion: .finished)
    } else if let error = error as? URLError {
    completion.send(completion: .failure(error))
    } else {
    fatalError("This should be unreachable, something is clearly wrong.")
    }

    }
    task.resume()
    return task.publisher(for: \.progress.completedUnitCount)
    .compactMap { [weak task] _ in task?.progress }
    .setFailureType(to: URLError.self)
    .map(TaskEither.left)
    .merge(with: completion.map(TaskEither.right))
    .eraseToAnyPublisher()
    }
    }

    关于swift - 实现与 URLSession 发布者和组合的重新连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57836518/

    55 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com