Moya是对 Alamofire的进一步封装,项目中准备着手使用moya来实现网络请求,使用moya简化了网络请求,简洁明了,方便维护,同时提供便利的单元测试入口,在swift中使用这个网络请求是一个不错的选择。
首先使用pod 导入moya,RxSwift,HandyJosn库
#将json数据转化成model
pod "HandyJSON", '~> 1.6.1'
#moya 对Alamofire 进行一次的封装
pod "Moya", '~> 8.0.5'
pod 'Moya/RxSwift'
#Swift函数响应式编程的一个开源库
pod "RxSwift", '~> 3.6.1'
1.定义一个枚举类型遵循targetType协议
协议里的方法有:
public protocol TargetType {
/// The target's base `URL`.
var baseURL: URL { get }
/// The path to be appended to `baseURL` to form the full `URL`.
var path: String { get }
/// The HTTP method used in the request.
var method: Moya.Method { get }
/// The parameters to be encoded in the request.
var parameters: [String: Any]? { get }
/// The method used for parameter encoding.
var parameterEncoding: ParameterEncoding { get }
/// Provides stub data for use in testing.
var sampleData: Data { get }
/// The type of HTTP task to be performed.
var task: Task { get }
/// Whether or not to perform Alamofire validation. Defaults to `false`.
var validate: Bool { get }
}
举个列子说明下:
enum BTLDiscoveryApiService {
case loadHomePageData(AnyObject)
}
extension BTLDiscoveryApiService:TargetType {
var baseURL: URL {
return URL.init(string: BTLApiConfigMacro.API_Default_ServerAddress)!
}
var path: String {
return ""
}
var method: Moya.Method {
switch self {
case .loadHomePageData(_):
return .get
}
}
var parameters: [String: Any]? {
switch self {
case .loadHomePageData(let reqMod):
let reqMod = reqMod as! BTLDiscoveryReqMod
return [BTLApiConfigMacro.API_Request_Key:reqMod.toJSONString()!]
}
}
var parameterEncoding: ParameterEncoding {
return URLEncoding.default
}
var sampleData: Data {
return "".data(using: String.Encoding.utf8)!
}
var task: Task {
return .request
}
var validate: Bool {
return false
}
}
1.新建请求model继承HandyJson
class BTLBaseReqModel: HandyJSON {
/** 手机唯一标识符 */
var imei:String?
required init() {
imei = "test"
}
}
class BTLDiscoveryReqMod: BTLBaseReqModel {
var productCode:String?
required init() {
super.init()
}
}
请求返回数据model
class BTLBaseResModel: HandyJSON {
/** 响应状态 200成功,其他失败 */
var status:NSInteger?
/** 建议的错误消息 */
var message:String?
/** 弹出窗的错误消息 级别重要 */
var dialogMessage:String?
/** 弹出窗的标题消息 */
var dialogTitle:String?
/** 响应消息编码 */
var code:String?
/** 登录信息token 如有值,则置换新的token */
var token:String?
/** 接口响应的时间戳 */
var timestamp:String?
required init() {
}
}
class BTLDiscoveryResMod: BTLBaseResModel {
var productId:String?
var productName:String?
required init() {
}
}
2.为了将网络请求返回的数据直接转化成model,写了一个modelTool扩展.
extension ObservableType where E == Response {
public func mapModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
return flatMap { response -> Observable<T> in
return Observable.just(try response.mapModel(T.self))
}
}
}
extension Response {
func mapModel<T: HandyJSON>(_ type: T.Type) throws -> T {
let jsonString = String.init(data: data, encoding: .utf8)
guard let object = JSONDeserializer<T>.deserializeFrom(json: jsonString) else {
throw MoyaError.jsonMapping(self)
}
return object
}
}
注:JSONDeserializer<T>.deserializeFrom(json: jsonString),这里使用的就是handyJson方法来实现将json格式数据转化成目标model
3.下边就可以发送一个简单的网络请求了:
class BTLDiscoveryViewController: BTLBaseViewController {
let provider = RxMoyaProvider<BTLDiscoveryApiService>()
let dispose = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
func loadData() {
let reqMod:BTLDiscoveryReqMod = BTLDiscoveryReqMod()
reqMod.productCode = "080300105127"
provider.request(.loadHomePageData(reqMod)).mapModel(BTLDiscoveryResMod.self).subscribe(onNext: { (model) in
}, onError: { (error) in
}, onCompleted: {
}) {
}.addDisposableTo(dispose)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}