demo地址
單獨(dú)的我就不多介紹了直接看github
RxSwift
Moya
ObjectMapper
cocoaPods只安裝上面的三個(gè)庫(kù)是不夠的杠娱,需要安裝帶有RxSwift擴(kuò)展的庫(kù),如下:
pod 'RxSwift', '~> 4.3.1'
pod 'RxCocoa', '~> 4.3.1'
pod 'Moya/RxSwift'
pod 'RxDataSources', '~> 3.1.0'
pod 'Moya-ObjectMapper/RxSwift'
1.在模塊里面建立一個(gè)文件夾她渴,里面新建一個(gè)API文件如圖
import Moya
import Alamofire
public enum ExampleAPI {
//獲取年檢詳細(xì)信息
case getExampleInfo(id:Int)
}
extension ExampleAPI:TargetType {
public var path: String {
switch self {
case .getExampleInfo:
return "/example/info"
}
}
public var method: Moya.Method {
switch self {
case .getExampleInfo:
return .get
}
}
public var sampleData: Data {
return "{}".data(using: String.Encoding.utf8)!
}
public var task: Task {
switch self {
case let .getExampleInfo(id: id):
return .requestParameters(parameters: ["id": id], encoding: URLEncoding.default)
}
}
public var headers: [String : String]? {
return ["uid": "456", "token": "123"]
}
public var baseURL: URL {
return UtimesBaseURL
}
}
2.模型文件
import ObjectMapper
struct ExampleInfo:Mappable {
var cost:Int = 0 //年檢費(fèi)用 ,
var rule:String = "" //規(guī)則
var timeDate:String = "" //年檢到期時(shí)間
var timeRemain:Int = 0 //剩余到期天數(shù)
var timeYear:String = "" //年檢年數(shù)
var feeText:String {
return String(format: "¥ %0.2f", CGFloat(CGFloat(cost)/CGFloat(100)))
}
init?(map: Map) {}
mutating func mapping(map: Map) {
cost <- map["cost"]
rule <- map["rule"]
timeDate <- map["time_date"]
timeRemain <- map["time_remain"]
timeYear <- map["time_year"]
}
}
2.全局通用的一個(gè)服務(wù)器返回的數(shù)據(jù)結(jié)構(gòu)(data是一個(gè)泛型抡医,適配不同的返回?cái)?shù)據(jù))
struct ResponseNormalModel<T:Mappable>:Mappable,Error{
var code : Int = defualtCode //狀態(tài)碼
var message: String = "" //消息
var data:T? //數(shù)據(jù)
init?(map: Map) {}
init(code:Int = defualtCode,message:String,data:T?) {
self.code = code
self.message = message
self.data = data
}
mutating func mapping(map: Map) {
code <- map["code"]
message <- map["msg"]
data <- map["data"]
}
}
provider設(shè)置
let MyProvider = JLProvider(endpointClosure: myEndpointClosure,
requestClosure: requestClosure,
stubClosure: MoyaProvider.neverStub,
callbackQueue: DispatchQueue.main,
manager: UtimesHTTPConfig.getSessionManager(),
plugins: [myNetworkLoggerPlugin,RequestLoadingPlugin()],
trackInflights: false)
// MARK: - 設(shè)置請(qǐng)求頭
private let myEndpointClosure = { (target: MultiTarget) -> Endpoint in
//處理URL
let url = target.baseURL.appendingPathComponent(target.path).absoluteString
let endpoint = Endpoint(url: url,
sampleResponseClosure: { .networkResponse(200, target.sampleData) },
method: target.method,
task: target.task,
httpHeaderFields: target.headers
)
do {
//設(shè)置通用header
var urlRequest = try endpoint.urlRequest()
urlRequest.httpBody = try? JSONSerialization.data(withJSONObject: publicParameters, options: .prettyPrinted)
} catch let error {
print(error)
}
return endpoint.adding(newHTTPHeaderFields: [ "Content-Type" : "application/json",])
}
// MARK: - 設(shè)置請(qǐng)求超時(shí)時(shí)間
private let requestClosure = { (endpoint: Endpoint, closure: @escaping MoyaProvider<MultiTarget>.RequestResultClosure) in
do {
var urlRequest = try endpoint.urlRequest()
urlRequest.timeoutInterval = 12
closure(.success(urlRequest))
} catch MoyaError.requestMapping(let url) {
closure(.failure(MoyaError.requestMapping(url)))
} catch MoyaError.parameterEncoding(let error) {
closure(.failure(MoyaError.parameterEncoding(error)))
} catch {
closure(.failure(MoyaError.underlying(error, nil)))
}
}
// MARK: - 調(diào)試plugin
let myNetworkLoggerPlugin = NetworkLoggerPlugin(verbose: true, output: reversedPrint, responseDataFormatter: { (data: Data) -> Data in
do {
let dataAsJSON = try JSONSerialization.jsonObject(with: data)
let prettyData = try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
return prettyData
} catch {
return data
}
})
func reversedPrint(_ separator: String, terminator: String, items: Any...) {
#if DEBUG
guard shouldShowLog else { return }
for item in items {
print(item, separator: separator, terminator: terminator)
}
#endif
}
let shouldShowLog = true //是否打印日志
//MARK: - 自定義Provider
import ObjectMapper
import RxSwift
class JLProvider: MoyaProvider<MultiTarget> {
let disposeBag:DisposeBag = DisposeBag()
override init(endpointClosure: @escaping MoyaProvider<Target>.EndpointClosure, requestClosure: @escaping MoyaProvider<Target>.RequestClosure, stubClosure: @escaping MoyaProvider<Target>.StubClosure, callbackQueue: DispatchQueue?, manager: Manager, plugins: [PluginType], trackInflights: Bool) {
super.init(endpointClosure: endpointClosure, requestClosure: requestClosure, stubClosure: stubClosure, callbackQueue: callbackQueue, manager: manager, plugins: plugins, trackInflights: trackInflights)
}
}
extension JLProvider{
func request<T:Mappable,U:TargetType>(target:U)-> Observable<T>{
return self.rx.request(target as! MultiTarget)
.filterSuccessfulStatusCodes()
.asObservable()
.filterSuccess(disposeBag: disposeBag, target: target as! MultiTarget)
.mapObject(T.self)
}
}
service文件
import SwiftyJSON
import RxSwift
import Moya
struct ExampleService {
let disposeBag:DisposeBag = DisposeBag()
func getExampleInfo(id:Int) -> Observable<ResponseNormalModel<ExampleInfo>> {
let target = MultiTarget(ExampleAPI.getExampleInfo(id: id))
return MyProvider.request(target: target)
}
}
調(diào)用
ExampleService().getExampleInfo(id: id)
.subscribe(onNext: { [weak self](model) in
//處理返回的數(shù)據(jù)
}, onError: { [weak self](error) in
//處理返回的錯(cuò)誤
}).disposed(by: disposeBag)
以上就是大概的4個(gè)流程