SmartNetwork

CI License

基于 URLSession 的轻量级封装,方便进行网络请求,并提供基于 Decodable 协议或自定义解码策略的强类型响应。

主要功能包括:

查看 SmartNetwork 的工作原理pdf 格式)。

Network scheme

查看 插件行为pdf 格式)。

Plugins behavior

基于这种现代接口的网络请求组织的新结构

public protocol RequestManager {
    /// ``Void`` request manager.
    var void: TypedRequestManager<Void> { get }

    /// ``Decodable`` request manager.
    var decodable: DecodableRequestManager { get }

    // MARK: - strong

    /// ``Data`` request manager.
    var data: TypedRequestManager<Data> { get }

    /// ``Image`` request manager.
    var image: TypedRequestManager<Image> { get }

    /// ``JSON`` request manager.
    var json: TypedRequestManager<Any> { get }

    // MARK: - optional

    /// ``Data`` request manager.
    var dataOptional: TypedRequestManager<Data?> { get }

    /// ``Image`` request manager.
    var imageOptional: TypedRequestManager<Image?> { get }

    /// ``JSON`` request manager.
    var jsonOptional: TypedRequestManager<Any?> { get }

    // MARK: - custom

    /// Custom request manager which can be used to create a request manager with a custom ``Deserializable`` of your own choice.
    func custom<T: Deserializable>(_ decoder: T) -> TypedRequestManager<T.Object> 

    /// Custom request manager which can be used to create a request manager with a custom ``Deserializable`` of your own choice.
    func customOptional<T: Deserializable>(_ type: T) -> TypedRequestManager<T.Object?>
}

具有简短自动完成功能的 API 的新用法

Task {
    let address: Address = "www.apple.com"
    let manager = SmartRequestManager.create()
    let result = await manager.decodable.request(TestInfo.self, address: address)
    switch result {
    case .success(let obj):
        // do something with response
    case .failure(let error):
        // do something with error
    }
}

Task {
    let address: Address = "www.apple.com"
    let manager = SmartRequestManager.create()
    manager.decodable.request(TestInfo.self, address: address) { result in
        switch result {
        case .success(let obj):
            // do something with response
        case .failure(let error):
            // do something with error
        }
    }
    .detach().deferredStart()
}

Task {
    let address: Address = "www.apple.com"
    let manager = SmartRequestManager.create()
    let result = await manager.request(address: address).decodeAsync(TestInfo.self)
    switch result {
    case .success(let obj):
        // do something with response
    case .failure(let error):
        // do something with error
    }
}

let address: Address = "www.apple.com"
let manager = SmartRequestManager.create()
manager.request(address: address).decode(TestInfo.self).complete { result in
    switch result {
    case .success(let obj):
        // do something with response
    case .failure(let error):
        // do something with error
    }
}
.detach().deferredStart()

自定义请求管理器

使用您自己的自定义可解码类型自定义您自己的网络

/// Custom decodable protocol for decoding data from response with specified keyPath
protocol KeyPathDecodable<Response> {
    associatedtype Response: Decodable
    static var keyPath: [String] { get }
}

extension SmartRequestManager {
    func keyPathed<T: KeyPathDecodable>(_ type: T.Type = T.self) -> TypedRequestManager<T.Response?> {
        return custom(KeyPathDecodableContent<T>())
    }
}

private struct KeyPathDecodableContent<T: KeyPathDecodable>: Deserializable {
    func decode(with data: RequestResult, parameters: Parameters) -> Result<T.Response?, Error> {
        if let error = data.error {
            return .failure(error)
        } else if let data = data.body {
            if data.isEmpty {
                return .failure(RequestDecodingError.emptyResponse)
            }

            do {
                let obj = try data.decode(T.Response.self, keyPath: T.keyPath)
                return .success(obj)
            } catch {
                return .failure(error)
            }
        } else {
            return .success(nil)
        }
    }
}