1,Alamofire网络框架请求数据
在iOS的工程中,之前用的是Alamofire网络框架,这个框架的一个网络请求示例如下:
func setUserStatus() {
let parameters:[String : Any] = ["userid": userid!]
Alamofire.request(URL_SET_USER_STATUS, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: nil).responseObject{[weak self]
(response :DataResponse<StatusModel>) in
if self == nil{
return
}
let ret = response.result.value
if response.result.error != nil{
......
}else{
.......
}
}
}
每个接口都需要拼接这些信息,包括api路径,请求的方式,参数,参数编码格式,消息头等几个主要部分,获取到网络数据后,再解析数据进行处理。
2,moya
moya的中文说明:https://github.com/Moya/Moya/blob/master/Readme_CN.md
它对网络请求的url和parameter进行了更深的封装
TargetType这个是使用moya必须要实现的一个协议,这个里面我们基本可以看到它封装的主要内容
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 }
/// Provides stub data for use in testing.这个数据是用在api测试时用的
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 }
/// The headers to be used in the request.
var headers: [String: String]? { get }
}
3,moya的使用示例
基本的使用示例:https://github.com/Moya/Moya/blob/master/docs/Examples/Basic.md
同样的接口封装成moya后
//Moya 10的版本已经去掉了RxMoyaProvider代码,直接用MoyaProvider
let provider = MoyaProvider<MyService>()
provider.rx.request(.setUserStatus)
.asObservable().mapJSON()
.mapObject(type: UserStatusModel.self)
.subscribe { [weak self] event in
if self == nil{
return
}
switch event {
case let .next(response):
//............
break
case let .error(error):
print(error)
//这个地方,处了网络异常外,对错误码也可处理
if let err = error as? NSError{
if err.domain == "Network"{
switch err.code{
case 401:
print("param invalide")
break
default:
print("other error")
}
}else{
print("other error")
}
}else{
print("other error")
}
break
default:
break
}
}.disposed(by: disposeBag)
4,ObjectMapper
获取到网络数据后,需要将json解析成对象数据,可配合ObjectMapper一起用。一般服务端返回的数据是
{
"code": 200,
"message": "",
"data": {}
}
这样我们可以对这些错误码进行统一处理,data数据解析成功后返回
import Foundation
import RxSwift
import ObjectMapper
import RxCocoa
extension Observable {
func mapObject<T: Mappable>(type: T.Type) -> Observable<T> {
return self.map { response in
//if response is a dictionary, then use ObjectMapper to map the dictionary
//if not throw an error
guard let dict = response as? [String: Any] else {
throw RxSwiftMoyaError.ParseJSONError
}
guard (dict["code"] as? Int) != nil else{
throw RxSwiftMoyaError.ParseJSONError
}
if let error = self.parseError(response: dict) {
throw error
}
return Mapper<T>().map(JSON: dict["data"] as! [String : Any])!
}
}
func mapArray<T: Mappable>(type: T.Type) -> Observable<[T]> {
return self.map { response in
guard response is [Any] else {
throw RxSwiftMoyaError.ParseJSONError
}
guard let dicts = response as? [String: Any] else {
throw RxSwiftMoyaError.ParseJSONError
}
guard (dicts["code"] as?Int) != nil else{
throw RxSwiftMoyaError.ParseJSONError
}
if let error = self.parseError(response: dicts) {
throw error
}
return Mapper<T>().mapArray(JSONArray: [dicts["data"] as! [String : Any]])
}
}
func parseServerError() -> Observable {
return self.map { (response) in
let name = type(of: response)
print(name)
guard let dict = response as? [String: Any] else {
throw RxSwiftMoyaError.ParseJSONError
}
if let error = self.parseError(response: dict) {
throw error
}
return self as! Element
}
}
//最外层的dictionary解析,将data数据取去后转换成json对象
//如果是错误码,抛异常处理
fileprivate func parseError(response: [String: Any]?) -> NSError? {
var error: NSError?
if let value = response {
var code:Int?
if let codes = value["code"] as? Int{
code = codes
}
if code != 200 {
var msg = ""
if let message = value["message"] as? String {
msg = message
}
error = NSError(domain: "Network", code: code!, userInfo: [NSLocalizedDescriptionKey: msg])
}
}
return error
}
}
enum RxSwiftMoyaError: String {
case ParseJSONError
}
extension RxSwiftMoyaError: Error {
}
至此,rxswift + moya就可以正常使用了
当然,moya的相比alamofire还有很多好用的功能,后面再跟大家分享
网友评论