分享一個(gè)自用的帶Rac擴(kuò)展的Moya網(wǎng)絡(luò)請(qǐng)求工具類

一.首先定義一個(gè)總的遵守TargetType的協(xié)議---方便擴(kuò)展,在這里可以設(shè)置默認(rèn)的請(qǐng)求方式,方便在寫具體的借口枚舉時(shí),直接設(shè)置path,parameters,省去了還得設(shè)置其它必須協(xié)議

extension APIable {
    var baseURL: URL {
        return URL(string: RequestManager<RequestOutData>.baseUrl)!
    }
    var method: Moya.Method { return .post }
    var task: Task { return .request }
    var parameterEncoding: ParameterEncoding { return URLEncoding.default }
    var sampleData: Data {
        return "".data(using: String.Encoding.utf8)!
    }
}

2.按接口使用類型分別定義遵守APIable協(xié)議的枚舉,比如說(shuō)

和賬號(hào)有關(guān)的
enum AccountAPI {
    //MARK: -登錄-
    case login(type: LoginPlatform)
}
extension AccountAPI: APIable {
    var path: String {
        switch self {
        case .login(type: let type):
            switch type {
            case .mobile(account: _, code: _):
                return "user/login.do"
            case .third(type: let third, openid: _, img: _, nick: _, ifbount: _):
                switch third {
                case .qq:       return "user/qqlogin.do"
                case .weixin:   return "user/wxlogin.do"
                case .weibo:    return "user/wblogin.do"
                }
            }
        }
    }
   
    var parameters: [String : Any]? {
        switch self {
        case .login(type: let type):
            switch type {
            case .mobile(account: let account, code: let code):
                return ["account": account, "code": code]
            case .third(type: _, openid: let openid, img: let img, nick: let nick, ifbount: let ifbount):
                let isOld = ifbount ? 1 : 0
                return ["openid": openid, "img": img, "nick": nick, "ifbount": "\(isOld)"]
            }
}
}

具體服務(wù)相關(guān)等等。。。。省略
/// 業(yè)務(wù)邏輯相關(guān)api
enum ServiceAPI {
    // MARK: - 搜索
    case search(nickname: String)
}

這樣寫的好處有:
1.不必所有借口都寫在一個(gè)文件里面,不易查找與修改
2.方便多人開(kāi)發(fā)時(shí),兩人都修改同一處代碼,提交報(bào)錯(cuò)問(wèn)題。。。

二:設(shè)置請(qǐng)求時(shí)的請(qǐng)求頭,請(qǐng)求超時(shí)等等

extension APIable {
    static func endpointClosure<T: APIable>() -> (T) -> Endpoint<T> {
        let endpointClosure = { (target: T) -> Endpoint<T> in
            let endpoint = Endpoint<T>(
                url: target.baseURL.appendingPathComponent(target.path).absoluteString,
                sampleResponseClosure: { .networkResponse(200, target.sampleData) },
                method: target.method,
                parameters: target.parameters,
                parameterEncoding: target.parameterEncoding)
            if let account = target as? AccountAPI {
                switch account {
                case .login(type: _), .getCode(mobile: _, mode: _):
                    return endpoint
                default:
                    return endpoint.adding(
                        httpHeaderFields: ["userid": "\(PreferenceManager.shared[.userid])",
                            "appsign": PreferenceManager.shared[.appsign] ?? ""
                        ])
                }
            } else {
                return endpoint.adding(
                    httpHeaderFields: ["userid": "\(PreferenceManager.shared[.userid])",
                        "appsign": PreferenceManager.shared[.appsign] ?? ""
                    ])
            }
        }
        return endpointClosure
    }
    
    static func requestClosure<T: APIable>() -> (Endpoint<T>, @escaping (Result<URLRequest, MoyaError>) -> Void) -> Void {
    
        let requestC = { (endpoint: Endpoint<T>, done: @escaping ((Result<URLRequest, MoyaError>) -> Void)) in
            if let urlRequest = endpoint.urlRequest {
                var request = urlRequest
                request.timeoutInterval = 10
                done(.success(request))
            } else {
                done(.failure(MoyaError.requestMapping(endpoint.url)))
            }
        }
        
        return requestC
    }
}

三:寫個(gè)網(wǎng)絡(luò)請(qǐng)求的提供工具--在這里使用第二步的網(wǎng)絡(luò)請(qǐng)求有關(guān)的設(shè)置

private struct ProviderManager {
    static let shared = ProviderManager()
    let apiProvider = ReactiveSwiftMoyaProvider<AccountAPI>(
        endpointClosure: AccountAPI.endpointClosure(),
        requestClosure: AccountAPI.requestClosure(),
        plugins: [NetworkActivityPlugin { UIApplication.shared.isNetworkActivityIndicatorVisible = $0 == .began },
                  NetworkLoggerPlugin(verbose: true)]
    )
    
    let serviceProvider = ReactiveSwiftMoyaProvider<ServiceAPI>(
        endpointClosure: ServiceAPI.endpointClosure(),
        requestClosure: ServiceAPI.requestClosure(),
        plugins: [NetworkActivityPlugin { UIApplication.shared.isNetworkActivityIndicatorVisible = $0 == .began },
                  NetworkLoggerPlugin(verbose: true)]
    )
    private init() {}
}

四:真正網(wǎng)絡(luò)請(qǐng)求的工具類:

struct RequestManager<Base> where Base: Mappable {
    private init() {}
    static var baseUrl: String { return BaseUrl.net.rawValue }
    //MARK: -返回單個(gè)model-
    static func requesObject(_ api: APIable) -> SignalProducer<Base, NetError> {
        let status = RealReachability.sharedInstance().currentReachabilityStatus()
        switch status {
        case .RealStatusNotReachable, .RealStatusUnknown:
          return SignalProducer<Base, NetError>(error: .content)
        case .RealStatusViaWiFi, .RealStatusViaWWAN:
            if let account = api as? AccountAPI {
                let producer: SignalProducer<Base, NetError> =
                    ProviderManager.shared.apiProvider
                        .request(account)
                        .toObject()
                return producer
            }
            else if let service = api as? ServiceAPI {
                let producer: SignalProducer<Base, NetError> =
                    ProviderManager.shared.serviceProvider
                        .request(service)
                        .toObject()
                return producer
            }
            else {
                fatalError()
            }
        }
    }
    //MARK: -返回?cái)?shù)組model-
    static func requestArray(_ api: TargetType) -> SignalProducer<[Base], NetError> {
        let status = RealReachability.sharedInstance().currentReachabilityStatus()
        switch status {
        case .RealStatusNotReachable, .RealStatusUnknown:
            return SignalProducer<[Base], NetError>(error: .content)
        case .RealStatusViaWiFi, .RealStatusViaWWAN:
            if let account = api as? AccountAPI {
                let producer: SignalProducer<[Base], NetError> =
                    ProviderManager.shared.apiProvider
                        .request(account)
                        .toArray()
                return producer
            }
            else if let service = api as? ServiceAPI {
                let producer: SignalProducer<[Base], NetError> =
                    ProviderManager.shared.serviceProvider
                        .request(service)
                        .toArray()
                return producer
            }
            else {
                fatalError()
            }
        }
    }
}

五: 外界使用:

searchAction: Action<String, Void, NetError> = Action({ nick in
            return RequestManager<SessionUser>
            .requestArray(ServiceAPI.search(nickname: nick))
                .map({ sessionUsers in
                    self.result.value = sessionUsers.map { $0.user }
                    reloadObserver.send(value: ())
                })
        })
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP、TCP、Http、Socket、X...
    Carden閱讀 5,311評(píng)論 0 12
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評(píng)論 25 709
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 近期,在直播節(jié)目《明日之子》中,薛之謙怒斥節(jié)目組黑幕,摔話筒憤然離去一度登上熱搜。 薛之謙憤然離席后,一般人的反應(yīng)...
    阿全不會(huì)文字閱讀 665評(píng)論 0 3
  • 最開(kāi)始聽(tīng)到這兩個(gè)詞,應(yīng)該是小學(xué)吧,排隊(duì)的時(shí)候,老師總是會(huì)說(shuō)“ 男生一排,女生一排,按大小個(gè)兒站好,閉嘴”。...
    君子一諾陳蘇閱讀 624評(píng)論 0 0

友情鏈接更多精彩內(nèi)容