FyNetWork
结合RxSwift、Moya、和HandyJSON封装网络请求模板
【该模板已经上传Github】-> 前往Github 获取代码
文件功能 Podfile 1 2 3 pod 'Moya /RxSwift' , '~> 12.0 .1 ' pod 'HandyJSON' , '~> 5.0 .1 '
FyUrls.swift 主要放一些请求Url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 struct FyUrls { #if DEBUG static let service: Bool = false #else static let service: Bool = true #endif static var domain: String { return FyUrls .service ? "https://v1.alapi.cn/" : "https://v1.alapi.cn/" } static var searchMusic: String { return "api/music/search" } }
FyApi 主要放基于Moya的网络请求配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 import Moyaenum FyApi { case search(keyword:String ) case other } extension FyApi :TargetType { var baseURL: URL { return URL (string: FyUrls .domain)! } var path: String { switch self { case .search: return FyUrls .searchMusic default : return "" } } var method: Moya .Method { switch self { case .search: return .get default : return .post } } var sampleData: Data { return "{}" .data(using: String .Encoding .utf8)! } var task: Task { switch self { case .search(let keyword): let params = FyParams .init (params: ["keyword" : keyword]) return .requestParameters(parameters: params.allParams, encoding: URLEncoding .default ) default : return .requestPlain } } var headers: [String : String ]? { switch self { default : return ["Content-type" : "application/json" ] } } }
FyRequest.swift 主要放Api接口请求方法具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 import UIKitimport Moyaimport RxSwiftlet requestTimeoutClosure = { (endpoint: Endpoint , done: @escaping MoyaProvider <FyApi >.RequestResultClosure ) in do { var request = try endpoint.urlRequest() if (request.url?.absoluteString.contains (FyUrls .searchMusic.lowercased()) ?? false ){ request.timeoutInterval = 30 request.addValue("zhangsan" , forHTTPHeaderField: "user" ) request.addValue("ahsfksjfhskdfhsjdkf" , forHTTPHeaderField: "cookie" ) }else { request.timeoutInterval = 10 } done(.success(request)) } catch { return } } class FyRequest : NSObject { static let request = FyRequest () var provider = MoyaProvider <FyApi > (requestClosure: requestTimeoutClosure,plugins: [NetworkLoggerPlugin (verbose: true )]) public func searchSongs (keyword:String) -> Single <Result <Songs >>{ return provider.rx.request(.search(keyword: keyword)) .filterSuccessfulStatusCodes() .mapModel() .flatMap { (result: FyResponse <Songs >) in if result.isSuccess{ return Single .just(Result .regular(result.data ?? Songs ())) }else { return Single .just(Result <Songs >.failing(RxMoyaError .reason(result.message ?? "" ))) } } .catchError({ error in return Single .just(Result .failing(RxMoyaError .reason(ErrorTips .netWorkError.rawValue))) }) } }
FyResponse.swift 主要是请求响应解析方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import UIKitimport Moyaimport RxSwiftimport HandyJSONextension Array : HandyJSON {}extension String : HandyJSON {}struct FyResponse <T :HandyJSON >:HandyJSON { var code:Int = 0 var message:String? var data: T? var isSuccess: Bool { return code == 200 } } extension Response { func mapModel <T>() throws -> FyResponse <T > { do { if let jsonString = String (data: data, encoding: String .Encoding .utf8){ if let obj = JSONDeserializer <FyResponse <T >>.deserializeFrom(json: jsonString) { return obj } throw RxMoyaError .modelMapping(self ) } else { throw RxMoyaError .modelMapping(self ) } } catch { throw RxMoyaError .modelMapping(self ) } } } extension PrimitiveSequence where TraitType == SingleTrait , ElementType == Response { func mapModel <T: HandyJSON>() -> Single <FyResponse <T >> { return flatMap { (response) -> Single <FyResponse <T >> in return Single .just(try response.mapModel()) } } }
FyNetError.swift 请求错误处理
FySongResponse.swift 请求歌曲列表model例子
FyViewModel.swift 网络请求库的运用例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import UIKitimport RxSwiftclass FyViewModel : NSObject { var dispose = DisposeBag () public typealias NetworkResultClosure = (_ names:String ) -> Void func fetchMusicListData (keyword:String,networkResultClosure: @escaping NetworkResultClosure) { _ = FyRequest .request.searchSongs(keyword: keyword).subscribe(onSuccess: { (result) in switch result{ case .regular(let songsInfo): var name:String = "" for song in songsInfo.songs{ name = name + "\n" + song.name } networkResultClosure(name) case .failing( _ ): break } }) { (error) in }.disposed(by: dispose) } } func loadData () { viewModel?.fetchMusicListData(keyword:"思如雪" ,networkResultClosure: {[weak self ] (names) in DispatchQueue .main.async { self ?.tips?.text = names } }) }
FyParams.swift 主要用来配置请求参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import UIKitclass FyBaseParams : NSObject { var channel : String { return "com.lpf.FyNetWork" } var vno : Int { return 100 } var baseParams:[String :Any ]?{ var tempParams:[String :Any ] = [String :Any ]() tempParams["channel" ] = channel tempParams["vno" ] = vno return tempParams } var allParams:[String :Any ]! } class FyParams : FyBaseParams { init (params:[String :Any ]? = [String :Any ]()) { super .init () var tempParams = [String :Any ]() for param in baseParams ?? [String :Any ](){ tempParams[param.key] = param.value } for param in params ?? [String :Any ](){ tempParams[param.key] = param.value } allParams = tempParams ?? [String :Any ]() } }