• 在Android开发中有非常强大的 Retrofit 请求,结合RxJava可以非常方便实现 RESTful API 网络请求。...Moya的可扩展性非常强,可以方便和RXSwift、ObjectMapper结合。 测试 REST API 定义 我们先用服务端定义几...

    在Android开发中有非常强大的 Retrofit 请求,结合RxJava可以非常方便实现 RESTful API 网络请求。在 iOS开发中也有非常强大的网络请求库 Moya ,Moya是一个基于 Alamofire 开发的,轻量级的Swift网络层。Moya的可扩展性非常强,可以方便和RXSwift、ObjectMapper结合。

    测试 REST API 定义

    我们先用服务端定义几个REST API,开发者根据自己的条件来实现。

    请求错误格式实例
    {
        "error": "密码错误",
        "error_code": "password_error"
    }
    测试 API 列表
    1. http://127.0.0.1:8080/account/login,参数username、password,post请求,成功响应为User
    2. http://127.0.0.1:8080/user/{userId},get请求,成功响应为User
    3. http://127.0.0.1:8080/user/query?q={keyword},get请求,成功响应为User列表

    创建接口

    // MyApiService.swift
    import Moya
    
    enum MyApiService {
        case login(username:String,password:String)
        case user(userId:String)
        case userQuery(keyword:String)
    }
    extension MyApiService:TargetType{
        // 定义请求的host
        var baseURL: URL {
            return URL(string: "http://127.0.0.1:8080")!
        }
        // 定义请求的路径
        var path: String {
            switch self {
            case .login(_, _):
                return "/account/login"
            case .user(let userId):
                return "user/\(userId)"
            case .userQuery(_):
                return "user/query"
            }
        }
        // 定义接口请求方式
        var method: Moya.Method {
            switch self {
            case .login:
                return .post
            case .user,.userQuery:
                return .get
            }
        }
        // 定义模拟数据
        var sampleData: Data {
            switch self {
            case .login(let username, _):
                return "{\"username\": \"\(username)\", \"id\": 100}".data(using: String.Encoding.utf8)!
            case .user(_):
                return "{\"username\": \"Wiki\", \"id\": 100}".data(using: String.Encoding.utf8)!
            case .userQuery(_):
                return "{\"username\": \"Wiki\", \"id\": 100}".data(using: String.Encoding.utf8)!
            }
        }
        // 构建参数
        var task: Task {
            switch self {
            case .login(let username, let passowrd):
                return .requestParameters(parameters: ["username": username,"passowrd": passowrd], encoding: URLEncoding.default)
            case .user(_):
                return .requestPlain
            case .userQuery(let keyword):
                return .requestParameters(parameters: ["keyword": keyword], encoding: URLEncoding.default)
            }
        }
        // 构建请求头部
        var headers: [String : String]? {
            return ["Content-type": "application/json"]
        }
    }

    请求数据

    let provider = MoyaProvider<MyApiService>()
    
    // Moya 提供最原始的请求方式,响应的数据是二进制
    provider.request(.user(userId: "101")){ result in
            // do something with the result
            let text = String(bytes: result.value!.data, encoding: .utf8)
        print("text1 = \(text)")
    }
    
    // 结合RxSwift,响应的数据是二进制
    provider.rx.request(.user(userId: "101")).subscribe({result in
            // do something with the result
            switch result {
            case let .success(response):
                let text = String(bytes: response.data, encoding: .utf8)
                print("text2 = \(text)")
            case let .error(error):
                print(error)
        }
    })
    
    // 通过mapJSON把数据转换成json格式
    provider.rx.request(.user(userId: "101")).mapJSON().subscribe({result in
            // do something with the result
            switch result {
            case let .success(text):
                print("text3 = \(text)")
            case let .error(error):
                print(error)
        }
    })
    // 通过mapJSON把数据转换成json格式,并转换成最常见的Observable
    provider.rx.request(.user(userId: "101")).mapJSON().asObservable().subscribe(onNext: { result in
            // do something with the result
            print("text4 = \(result)")
    }, onError:{ error in
        // do something with the error
    })
    请求数据:RxBlocking

    RxBlocking使用教程 ,可以使用同步的方式请求网络

    import RxBlocking
    
    do{
        let text = try provider.rx.request(.user(userId: "101")).mapJSON().toBlocking().first()
        print("text5 = \(text)")
    }catch{
        print(error)
    }

    结合 ObjectMapper

    引入ObjectMapper
    pod 'ObjectMapper', '~> 3.4'
    编写RxSwift拓展代码
    //  MoyaRxSwiftObjectMapperExtension.swift
    
    import Foundation
    import RxSwift
    import Moya
    import ObjectMapper
    
    public extension PrimitiveSequence where TraitType == SingleTrait, ElementType == Response {
        func mapObject<T: BaseMappable>(type: T.Type) -> Single<T> {
            return self.map{ response in
                return try response.mapObject(type: type)
            }
        }
        func mapArray<T: BaseMappable>(type: T.Type) -> Single<[T]> {
            return self.map{ response in
                return try response.mapArray(type: type)
            }
        }
    }
    public extension ObservableType where E == Response {
        func mapObject<T: BaseMappable>(type: T.Type) -> Observable<T> {
            return self.map{ response in
                return try response.mapObject(type: type)
            }
        }
        func mapArray<T: BaseMappable>(type: T.Type) -> Observable<[T]> {
            return self.map{ response in
                return try response.mapArray(type: type)
            }
        }
    }
    
    public extension Response{
        func mapObject<T: BaseMappable>(type: T.Type) throws -> T{
            let text = String(bytes: self.data, encoding: .utf8)
            if self.statusCode < 400 {
                return Mapper<T>().map(JSONString: text!)!
            }
            do{
                let serviceError = Mapper<ServiceError>().map(JSONString: text!)
                throw serviceError!
            }catch{
                if error is ServiceError {
                    throw error
                }
                let serviceError = ServiceError()
                serviceError.message = "服务器开小差,请稍后重试"
                serviceError.error_code = "parse_error"
                throw serviceError
            }
        }
        func mapArray<T: BaseMappable>(type: T.Type) throws -> [T]{
            let text = String(bytes: self.data, encoding: .utf8)
            if self.statusCode < 400 {
                return Mapper<T>().mapArray(JSONString: text!)!
            }
            do{
                let serviceError = Mapper<ServiceError>().map(JSONString: text!)
                throw serviceError!
            }catch{
                if error is ServiceError {
                    throw error
                }
                let serviceError = ServiceError()
                serviceError.message = "服务器开小差,请稍后重试"
                serviceError.error_code = "parse_error"
                throw serviceError
            }
        }
    }
    class ServiceError:Error,Mappable{
        var message:String = ""
        var error_code:String = ""
        required init?(map: Map) {}
        init() {
            
        }
        func mapping(map: Map) {
            error_code <- map["error_code"]
            message <- map["error"]
        }
        var localizedDescription: String{
            return message
        }
    }
    
    创建 User 类
    //  User.swift
    import ObjectMapper
    class User: Mappable {
        required init?(map: Map) {}
        
        func mapping(map: Map) {
            userId <- map["userId"]
            name <- map["name"]
            age <- map["age"]
        }
        
        var userId:Int = 0
        var name:String = ""
        var age:Int = 0
    }
    测试
    do{
        let user = try provider.rx.request(.user(userId: "101")).mapObject(type: User.self).toBlocking().first()
        print("user.name = \(user?.name)")
    }catch{
        print(error)
    }
    do{
        let user = try provider.rx.request(.user(userId: "101")).asObservable().mapObject(type: User.self).toBlocking().first()
        print("user.name = \(user?.name)")
    }catch{
        print(error)
    }
    
    do{
        let users = try provider.rx.request(.userQuery(keyword: "Wiki")).mapArray(type: User.self).toBlocking().first()
        print("test8 users.count = \(users?.count)")
    }catch{
        if error is ServiceError {
            print((error as! ServiceError).message)
        }
        print(error)
    }

    打印日志

    private func JSONResponseDataFormatter(_ data: Data) -> Data {
        do {
            let dataAsJSON = try JSONSerialization.jsonObject(with: data)
            let prettyData =  try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
            return prettyData
        } catch {
            return data // fallback to original data if it can't be serialized.
        }
    }
    let provider = MoyaProvider<MyApiService>(plugins: [NetworkLoggerPlugin(verbose: true, responseDataFormatter: JSONResponseDataFormatter)])

    转载于:https://www.cnblogs.com/taoweiji/p/11538178.html

    展开全文
  • 在主要的MainViewController.swift中: import UIKit ...import Moya import RxSwift class MainViewController: UITabBarController {  let provider = RxMoyaProv
  • 优雅的网络请求本人已写了一个开源的拿来及用的[Swift项目框架](https://github.com/liuniuliuniu/LLProgramFramework.Swift) 可以参考此框架来通篇阅读此文章更有帮助 有喜欢的还望送人玫瑰手留余香哦 ...
  • RxSwift 实例讲解 总结   Moya   TargetType /// The protocol used to define the specifications necessary for a `MoyaProvider`. public protocol TargetType { /// The target'...
  • 之前写过Alamofire的简单使用,但是一般开发中都会对这些第三库封装,然后使用,之前自己封装的demo也是借鉴了一些Moya的设计思路。今天就介绍一下Moya一个帮助你处理网络层的第三方框架。 介绍 Moya Moya是一个...
  • RxSwift学习之十一 (Rxswift+Moya+Alamofire)
  • 废话不多说直接上代码 // // MoyaNetWorking.swift // GreenAir // // Created by BruceAlbert on 2017/9/18. // Copyright © 2017年 Mars. All rights reserved. ...import Moya //import Alam...
  • 项目Demo地址 打造swift网络框架 准备工作 使用CocoaPods工具Pod需要... pod 'Moya/RxSwift' pod 'HandyJSON', '~> 5.0.0-beta.1' 创建文件 APIManager // // APIManager.swift // SwiftNetWorkHelper
  • RxSwift+Moya之项目实战 2017-10-08 18:59:23
    RxSwift+Moya之项目实战 RxSwift相关基本介绍和用法可参考: RxSwift的使用详解01 RxSwift的使用详解02 一. 下面将将进行实战项目 1.登录注册功能 输入用户名要大于6个字符,不然密码不能输入 密码必须大于6个...
  • moya+RxSwift+HandyJSON 学习 2017-08-03 10:39:00
    Moya是对 Alamofire的进一步封装,项目中准备着手使用moya来实现网络请求,使用moya简化了网络请求,简洁明了,方便维护,同时提供便利的单元测试入口,在swift中使用这个网络请求是一个不错的选择。 1.定义一个枚举...
  • Rx 是微软出品的一个 Funtional Reactive Programming 框架,RxSwift 是它的一个 Swift 版本的实现。 RxSwift 的主要目的是能简单的处理多个异步操作的组合,和事件/数据流。 利用 RxSwift,我们可以把本来要分散...
  • 文章目录开源项目分析(SwiftHub)架构分析(一)1. SwiftHub项目简介2. SwiftHub项目采用的架构 开源项目分析(SwiftHub)架构分析(一) 1. SwiftHub项目简介 2. SwiftHub项目采用的架构 ...
  • moya + RxSwift 进行网络请求 2017-03-14 14:16:17
    1.关于moya如在OC中使用AFNetworking一般,Swift我们用Alamofire来做网络库.而Moya在Alamofire的基础上又封装了一层:官方说moya有以下特性(我也就信了): 编译时检查正确的API端点访问. 使你定义不同端点枚举值对应...
  • RxSwift + MVVM 初体验 2019-09-11 07:17:44
    一、原起 作为一名iOS开发者,必须跟上时代的潮流,随着...最近使用RxSwift+MVVM+Moya进行了swift的体验之旅。加入到swift开发的大潮中去。 二、目录结构 这个demo的项目结构包括:View、Model、ViewModel、Cont...
  • 最近在新项目中尝试使用 Moya+RxSwift+Argo 进行网络请求和解析,感觉还阔以,再来给大家安利一波。 Moya Moya 是一个基于 Alamofire 的更高层网络请求封装,深入学习请参见官方文档:Moya/Docs。
  • 如何写出最简洁优雅的网络封装 Moya + RxSwift
  • 这里只解释我对MVVM的理解,不再对RxSwiftMoya、Codable、MVVM做过多的叙述,相信Google会让你知道的更多。 一、目录结构 二、网络请求 1、相同格式数据的处理 对于Json的数据返回会有一个统一的返...
  • 最近在新项目中尝试使用 Moya+RxSwift+Argo 进行网络请求和解析,感觉还阔以,再来给大家安利一波。 Moya Moya是一个基于Alamofire的更高层网络请求封装,深入学习请参见官方文档:Moya/Doc...
  • 主要是练习Moya的熟练使用,全文涉及到CYLTabBarController搭建简单易用的框架、Swift和OC互相调用、FLEX显示界面层级UI的属性、ObjectMapper解析数据、Kingfisher加载网络图片、MBProgressHUD融合到请求里自动显示...
  • 前言之前的几篇博客算是入门篇,那么这篇就是RxSwift的实战篇。由于对RxSwift的认识还不够深刻,所以项目中没有使用MVVM模型,以及编程思想也还没转变过来。该项目是参考https://github.com/kLike/ZhiHu-RxSwift实现...
1 2 3 4 5 ... 11
收藏数 217
精华内容 86