我想知道是否有一种方法可以使用新的Apple框架实现重新连接机制结合使用URLSession发布者
waitsForConnectivity不走运(它甚至没有在自定义会话中调用委托)URLSession.background但在发布过程中崩溃了。我也不明白我们如何以这种方式跟踪进度
有没有人已经尝试过这样做?
更新:
似乎在 Xcode 11 Beta 中waitsForConnectivity 不起作用
upd2:
Xcode 11 GM -waitsForConnectivity正在运行,但只能在设备上运行。使用默认会话,设置标志并实现会话委托。task is waiting for connectivity无论您是否使用带回调的 init 任务,都会调用方法。
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)
}
}
Run Code Online (Sandbox Code Playgroud)
你试过retry(_:)了吗?它\xe2\x80\x99s 可在Publisher,并在失败时重新运行请求。
如果您不\xe2\x80\x99 不希望请求针对所有失败立即重新运行,那么您可以使用catch(_:)并决定哪些故障需要重新运行。
这是一些获取进度的代码。
\n\nenum Either<Left, Right> {\n case left(Left)\n case right(Right)\n\n var left: Left? {\n switch self {\n case let .left(value):\n return value\n case .right:\n return nil\n }\n }\n\n var right: Right? {\n switch self {\n case let .right(value):\n return value\n case .left:\n return nil\n }\n }\n}\n\nextension URLSession {\n func dataTaskPublisherWithProgress(for url: URL) -> AnyPublisher<Either<Progress, (data: Data, response: URLResponse)>, URLError> {\n typealias TaskEither = Either<Progress, (data: Data, response: URLResponse)>\n let completion = PassthroughSubject<(data: Data, response: URLResponse), URLError>()\n let task = dataTask(with: url) { data, response, error in\n if let data = data, let response = response {\n completion.send((data, response))\n completion.send(completion: .finished)\n } else if let error = error as? URLError {\n completion.send(completion: .failure(error))\n } else {\n fatalError("This should be unreachable, something is clearly wrong.")\n }\n\n }\n task.resume()\n return task.publisher(for: \\.progress.completedUnitCount)\n .compactMap { [weak task] _ in task?.progress }\n .setFailureType(to: URLError.self)\n .map(TaskEither.left)\n .merge(with: completion.map(TaskEither.right))\n .eraseToAnyPublisher()\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1152 次 |
| 最近记录: |