Moya
初探若是你上面的POP面向协议编程已经看得差很少了,那么这个模块内容是很是简单的!git
常规网络层在iOS应用程序中很常见。它们很差有几个缘由:github
Moya
的基本思想是:咱们须要一些网络抽象层,可以充分封装直接调用Alamofire。它应该足够简单,普通的事情很容易,可是足够全面,复杂的事情也很容易。
编程
Moya
的特色有如下几点:Moya
开发使用1:接口枚举json
public enum LGLoginAPI {
case login(String, String, String) // 登陆接口
case smscode(String) // 登陆,发送验证码
case otherRequest // 其余接口,没有参数
}
复制代码
extension LGLoginAPI: TargetType {
//服务器地址
public var baseURL: URL {
return URL(string:"http://127.0.0.1:5000/")!
}
// 各个请求的具体路径
public var path: String {
switch self {
case .login:
return "login/"
case .smscode:
return "login/smscode/"
case .otherRequest:
return "login/otherRequest/"
}
}
// 请求方式
public var method: Moya.Method {
switch self {
case .login:
return .post
case .smscode:
return .post
default:
return .get
}
}
//这个就是作单元测试模拟的数据,只会在单元测试文件中有做用
public var sampleData: Data {
return "{}".data(using: String.Encoding.utf8)!
}
//请求任务事件(这里附带上参数)
public var task: Task {
var param:[String:Any] = [:]
switch self {
case .login(let username,let password,let smscode):
param["username"] = username
param["password"] = password
param["smscode"] = smscode
case .smscode(let username):
param["username"] = username
default:
return .requestPlain
}
return .requestParameters(parameters: param, encoding: URLEncoding.default)
}
//设置请求头
public var headers: [String: String]? {
return nil
}
}
复制代码
baseURL
:服务器地址host 处理path
:根据不一样的接口,肯定各个请求的具体路径method
:根据不一样的接口,设置请求方式headers
:统一配置的请求头信息配置task
:配置内部参数,以及task信息2:登陆模块网络管理者api
class LGLoginClient: NSObject {
static let manager = LGLoginClient()
//MARK: - 验证码事件
func smscode(username:String,complete:@escaping ((String) -> Void)) {
let provide = MoyaProvider<LGLoginAPI>()
provide.request(.smscode(username)) { (result) in
switch result{
case let .success(response):
let dict = LGLoginClient.lgJson(data: response.data)
complete(dict["smscode"] as! String)
case let .failure(error):
print(error)
complete("")
}
}
}
}
复制代码
MoyaProvider
是这次网络请求的信息提供者MoyaProvider
根据模块 LGLoginAPI
设置的信息绑定数据请求MoyaProvider
经过调用 request
方法传出这次请求的接口,可是参数须要应用层提供!json
序列化!携带信息的闭包
给应用层3:应用层调用数组
@IBAction func didClickCodeBtn(_ sender: Any) {
LGLoginClient.manager.smscode(username: username) { [weak self](smscode) in
self?.smscodeTF.text = smscode
}
}
复制代码
Moya模型总结:CFNextwork -> Alamofire -> Moya -> 业务层服务器
Moya
直接使用的弊端RxSwift
(毕竟如今函数响应式编程已成为趋势),显然咱们更须要序列,由于序列能够直接绑定响应UI,更便于开发!Moya
对咱们来讲还缺了很严重的一步:模型化Moya模型总结:CFNextwork -> Alamofire -> Moya -> 模型化 -> RxSwift -> 业务层网络
为了可以增长 Moya
序列化的能力,作了 Reactive
拓展!闭包
public extension Reactive where Base: MoyaProviderType {
/// Designated request-making method with progress.
public func requestWithProgress(_ token: Base.Target, callbackQueue: DispatchQueue? = nil) -> Observable<ProgressResponse> {
let progressBlock: (AnyObserver) -> (ProgressResponse) -> Void = { observer in
return { progress in
observer.onNext(progress)
}
}
let response: Observable<ProgressResponse> = Observable.create { [weak base] observer in
let cancellableToken = base?.request(token, callbackQueue: callbackQueue, progress: progressBlock(observer)) { result in
switch result {
case .success:
observer.onCompleted()
case let .failure(error):
observer.onError(error)
}
}
return Disposables.create {
cancellableToken?.cancel()
}
}
}
复制代码
observer.onNext(progress)
observer.onCompleted()
和 observer.onError(error)
RxSwift
封装的销毁对外提供,外界随时随地断开响应关系!Moya
包装一层 RxSwift
MoyaProvider
初始化对象调用:rx.request(target)
毕竟咱们开发人员更多的关注是模型,而非 data
、抑或 json
架构
extension PrimitiveSequence where TraitType == SingleTrait, Element == Moya.Response {
func map<T: ImmutableMappable>(_ type: T.Type) -> PrimitiveSequence<TraitType, T> {
return self
.map { (response) -> T in
let json = try JSON(data: response.data)
guard let code = json[RESULT_CODE].int else { throw RequestError.noCodeKey }
if code != StatusCode.success.rawValue { throw RequestError.sysError(statusCode:"\(code)" , errorMsg: json[RESULT_MESSAGE].string) }
if let data = json[RESULT_DATA].dictionaryObject {
return try Mapper<T>().map(JSON: data)
}else if let data = json[RESULT_RESULT].dictionaryObject {
return try Mapper<T>().map(JSON: data)
}
throw RequestError.noDataKey
}.do(onSuccess: { (_) in
}, onError: { (error) in
if error is MapError {
log.error(error)
}
})
}
}
复制代码
PrimitiveSequence
实际对象是处理 Moya.Response
SwiftyJSON
把 Response
的 data
解析成 json
ObjectMapper
转成相应模型数据[T]
就 OKloginService.login().asObservable()
.subscribe(onNext: {[weak self] (rcmdBranchModel) in
guard let `self` = self else { return }
self.requestIds = rcmdBranchModel.tab.map{$0.id}
self.menuTitles += rcmdBranchModel.tab.map{$0.name}
self.pageController.magicView.reloadData(toPage: 1)
})
.disposed(by: disposeBag)
复制代码
LGLoginClient
接受业务层的响应及时处理条件交付给 MoyaProvider
MoyaProvider
也就是咱们的 Moya
层调度集中管理继续下沉给 Alamofire
Alamofire
包装处理请求,交给 CFNextwork
去真正处理网络下层CFNextwork
请求得到 Response
经过代理交付给 Alamofire
Alamofire
经过包装、验证、序列化回调给封装它的 Moya
Moya
这一层经过 SwiftyJSON
进行 json化
,通过 ObjectMapper
进行 模型化
Moya
再通过 RxSwift
进行 序列化
模块网络层
回调出去相应的 模型序列
给应用层整个流程构成一个闭环,层层下沉,层层上浮!架构思路很是清晰!
当北京赶上西雅图(人生大幸),当
Moya
赶上RxSwift
(开发大幸)!架构设计思惟并非一天就能养成
(Rome was not built in a day)
可是若是你是一个中高级开发,那么架构设计思惟你必须拥有。前进道路一点一滴,慢慢积累。上帝也会可怜你.....💪💪💪就问此时此刻还有谁?45度仰望天空,该死!我这无处安放的魅力!