Swift 简单方便的网络框架

在最近的和目APP中,在设计网络请求架构的时候,对于平台文档中,每一个接口我们都需要单独封装一个接口一一对应,有没有什么方式能够统一呢?只是request和response不一样。基础请求都是post?于是我使用了JSONExport+SwiftHTTP+SwiftyJSON+RxSwift+ObjectMapper+Realm进行网络请求和解析,感觉使用起来非常方便,节约了APP梳理平台接口的时间,在这里给大家安利一波。

Swift 简单方便的网络框架

介绍

首先大致介绍每个框架在其充当的什么角色。

  1. JSONExport
    JSONExport是把Json转成Swift的struct或者class,只要平台接口文档书写正确,直接可以输出相应的对象。
    例子:
  2. SwiftHTTP
    SwiftHTTP本质是基于NSURLSession,并做了封装。使用SwiftHTTP可以让我们网络请求相关代码(如获取数据,提交数据,上传文件,下载文件等)更加简洁易用。当然这里网络请求框架你也可以用NSURLSession自己写,也可以用Alamofire或Moya。
  3. SwiftyJSON
    SwiftyJSON是个使用Swift语言编写的开源库,可以让我们很方便地处理JSON数据(解析数据、生成数据),并且能够避免解包造成的崩溃。
  4. RxSwift
    RxSwift是一个函数式响应式编程的开源框架,以前的博客也有相关的介绍。
  5. ObjectMapper
    ObjectMapper 是一个在 Swift 下数据转模型的非常好用,可以Json转Model,Model转Json使用起来非常方便。
  6. Realm
    Realm是一个轻量级的数据库,在iOS开发过程中,使用起来非常方便

设计思路

所有接口的入参,可以根据平台文档,通过JSONExport生成入参对象的Model。然后把Model转Json经过统一的请求。请求回来的数据根据平台文档通过JSONExport生成Model,请求返回的数据,根据自己业务需求或平台文档map成自己需要的model。在请求的过程中,可以通过请求配置是否需要缓存请求数据。

  1. 首先创建一个class文件,命名为HMSDK.swift,导入需要使用的框架
1
2
3
4
5
6
import RxSwift
import ObjectMapper
import RxCocoa
import RxRealm
import RealmSwift
import SwiftyJSON
  1. 初始化配置
1
2
3
4
5
6
7
/// 单例
public static var shared : HMSDK {
struct HMSDKInstance {
static let instance : HMSDK = HMSDK()
}
return HMSDKInstance.instance
}
  1. 请求接口地址配置
1
2
3
4
5
6
7
8
/// 接口
/// 填写你的接口地址
public let serviceURL = "http://192.168.1.1"
private let disposeBag = DisposeBag()
/// 更多基础配置
...
...
  1. 基础网络请求
1
2
3
public func request<T: Mappable>(_ param: T) -> Observable<Any>{
return rx_request(param.toJSON())
}

使用RxSwift进行扩展

1
2
3
4
5
6
7
8
9
10
extension HMSDK {
public func rx_request(_ reqParams: [String: Any]) -> Observable<Any> {
return Observable<Any>
.create { (subscriber) -> Disposable in
// 这里面做基础请求,缓存,以及数据处理
return Disposables.create()
}
.observeOn(MainScheduler.init())
}
}
  1. 请求回来的数据进行业务对接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
extension Observable{
/// 解析JSON到Struct
///
/// - Parameter type: Model
/// - Returns: Observable
public func mapObject<T: Mappable>(type: T.Type) -> Observable<T>{
return observeOn(SerialDispatchQueueScheduler.init(qos: .background))
.map({ representor in
guard let response = representor as? HMSDKResponseParamable else {
throw HMSDKError.noRepresentor
}
if response.resultCode == "000000"{
return Mapper<T>().map(JSON: response.data! as! [String : Any])!
}else{
throw HMSDKError.error(resultCode: response.resultCode, resultMsg: response.resultMsg)
}
})
.observeOn(MainScheduler.instance)
}
/// 解析JSON到Struct的数组
///
/// - Parameter type: Model
/// - Returns: Observable
public func mapArray<T: Mappable>(type: T.Type, key: String? = nil) -> Observable<[T]>{
return observeOn(SerialDispatchQueueScheduler.init(qos: .background))
.map({ representor in
guard let response = representor as? HMSDKResponseParamable else {
throw HMSDKError.noRepresentor
}
if response.resultCode == "000000"{
guard (response.data != nil) else{
throw HMSDKError.noData
}
// to array
let json = JSON(response.data!)
if json.type == .array {
return Mapper<T>().mapArray(JSONArray: json.arrayObject as! [[String : Any]])!
}
if json.type == .dictionary{
guard (key != nil) else {
let newKey = json.dictionary?.keys.first
return Mapper<T>().mapArray(JSONArray: json[newKey!].arrayObject as! [[String : Any]])!
}
return Mapper<T>().mapArray(JSONArray: json[key!].arrayObject as! [[String : Any]])!
}
throw HMSDKError.noData
}else{
throw HMSDKError.error(resultCode: response.resultCode, resultMsg: response.resultMsg)
}
})
.observeOn(MainScheduler.instance)
}
}

实战

基础请求参数封装

根据平台文档,对基础请求参数做封装,转成Model如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//
// HMRequestModel.swift
// BigHeMu
//
// Created by austin on 2017/4/19.
// Copyright © 2017年 BigHeMu. All rights reserved.
//
import Foundation
import ObjectMapper
import RxSwift
import RxCocoa
protocol RequestParamable {
/// 应用标识
var appid: String {get set}
/// 时间戳
var timestamp: String {get set}
/// 版本号
var version: String? {get set}
/// 序列号
var msgSeq: String? {get set}
/// 服务名
var serviceName: String? {get set}
/// 方法名
var methodName: String? {get set}
/// 鉴权token
var token: String? {get set}
/// 接口请求参数
var parameters: [String : Any]? {get set}
/// parameters参数rsa签名
var signature: String? {get set}
/// 添加基础请求平台
var OS: String? {get set}
}
struct RequestParam: RequestParamable, Mappable{
/// 添加基础请求平台
var OS: String? = "iOS"
var appid: String = "ANDMU-APP"
var timestamp: String = {
let timestamp = Int64(NSDate().timeIntervalSince1970*1000)
return "\(timestamp)"
}()
var msgSeq: String? = String(format: "%010d", andlink.requestIndex)
var serviceName: String?
var methodName: String?
var version: String? = Bundle.main.infoDictionary? ["CFBundleShortVersionString"] as? String
var token: String?
var parameters: [String : Any]?
var signature: String?
public init() {
}
public init?(map: Map) {
}
mutating func mapping(map: Map) {
appid <- map["appid"]
timestamp <- map["timestamp"]
msgSeq <- map["msgSeq"]
serviceName <- map["serviceName"]
methodName <- map["methodName"]
version <- map["version"]
token <- map["token"]
parameters <- map["parameters"]
signature <- map["signature"]
OS <- map["OS"]
}
}
protocol ConvertToRequestParamable: Mappable{
func baseRequestParam() -> RequestParam
func toRequestParam() -> [String:Any]
}
extension ConvertToRequestParamable where Self: Any{
func baseRequestParam() -> RequestParam{
var reqParams = RequestParam()
reqParams.token = HMSDK.shared.token
reqParams.parameters = self.toJSON()
reqParams.signature = reqParams.parameters?.jsonSign
return reqParams
}
}

基础返回参数封装

根据平台文档,对基础返回参数做封装,转成Model如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//
// HMResponeModel.swift
// BigHeMu
//
// Created by austin on 2017/4/19.
// Copyright © 2017年 BigHeMu. All rights reserved.
//
import Foundation
import ObjectMapper
import RxSwift
import RxCocoa
protocol HMResponseParamable{
/// 错误码
var resultCode: String? {get set}
/// 错误码描述
var resultMsg: String? {get set}
/// 消息码
var msgSeq: String? {get set}
/// 操作返回的结果
var data: Any? {get set}
var total: Int? {get set}
var page: Int? {get set}
var pageSize: Int? {get set}
/// 扩展字段
var xxx: [String : Any]? {get set}
}
struct HMResponseParam: HMResponseParamable, Mappable{
/// 操作返回的结果
var resultCode: String?
var resultMsg: String?
var msgSeq: String?
var data: Any?
var total: Int?
var page: Int?
var pageSize: Int?
var xxx: [String : Any]?
public init(){
}
public init?(map: Map) {
}
mutating func mapping(map: Map) {
resultCode <- map["resultCode"]
resultMsg <- map["resultMsg"]
msgSeq <- map["msgSeq"]
data <- map["data"]
total <- map["total"]
page <- map["page"]
pageSize <- map["pageSize"]
xxx <- map["xxx"]
}
}

缓存文件以及加密配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public enum HMCache: Int {
/// 不用缓存,返回网络数据
case none = 0
/// 有缓存返回缓存,无缓存返回网络请求数据
case only = 1
/// 先返回缓存,再返回网络请求数据
case both = 2
}
fileprivate var realmConfig: RLMRealmConfiguration = {
let config = RLMRealmConfiguration.default()
let realmFilePath = config.fileURL!.deletingLastPathComponent()
.appendingPathComponent("HMCache.realm")
config.fileURL = realmFilePath
// 获取我们的 Realm 文件的父级目录
let folderPath = config.fileURL!.deletingLastPathComponent().path
// 解除这个目录的保护
try! FileManager.default.setAttributes([FileAttributeKey.protectionKey: FileProtectionType.none], ofItemAtPath: folderPath)
config.schemaVersion = 1
config.deleteRealmIfMigrationNeeded = true
let key = Data(bytes: [0x41, 0x59, 0x57, 0x54, 0x50, 0x44, 0x37, 0x42,
0x48, 0x41, 0x59, 0x57, 0x54, 0xaa, 0x4a, 0x3a,
0x4f, 0x48, 0x41, 0x59, 0x57, 0x42, 0x50, 0x43,
0xaa, 0xff, 0x48, 0x41, 0x42, 0x57, 0x54, 0x50,
0x51, 0x5a, 0x4f, 0x42, 0x41, 0x59, 0x57, 0x54,
0x53, 0x51, 0x42, 0x4f, 0x48, 0x41, 0x59, 0x57,
0x4b, 0x42, 0x51, 0x5a, 0x4f, 0x48, 0x41, 0x59,
0x42, 0x4b, 0x53, 0x51, 0x5a, 0x4f, 0x48, 0x41])
config.encryptionKey = key
return config
}()
/// 配置数据库(如果不需要修改默认数据库的,就不调用这个方法)
func creatDataBase() {
// //获取当前配置
RLMRealmConfiguration.setDefault(self.realmConfig)
}
/// 缓存请求对象
/// realm数据库保存的模型(必须保存statusCode字段,因为离线数据要用到状态码来判断是否是一次成功请求)
class ResultModel: RLMObject {
dynamic var data: Data? = nil
dynamic var statuCode: Int = 0
dynamic var key: String = ""
dynamic var time: String? = ""
//设置数据库主键
override static func primaryKey() -> String? {
return "key"
}
}

请求环境配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@objc public enum HMEnvironment: Int{
case dev = 0
case test = 1
case pro = 2
}
public var environment: HMEnvironment = .test {
didSet{
if environment == .dev {
self.serviceURL = "http://xxx.xxx.xxx"
}
if environment == .test {
self.serviceURL = "http://xxx.xxx.xxx"
}
if environment == .pro {
self.serviceURL = "http://xxx.xxx.xxx"
}
}
}

错误处理配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
struct ANDLINKError : Error {
enum HMError : Error{
case unknown
case noRepresentor
case notSuccessfulHTTP
case noData
case notMakeObjectError
}
var errorType: HMError = .unknown
var resultCode: String?
var resultMsg: String?
init(resultCode: String?, resultMsg: String?) {
self.errorType = .unknown
self.resultCode = resultCode
self.resultMsg = resultMsg
}
init(_ errorType: HMError = .unknown) {
self.errorType = errorType
if self.errorType == .noRepresentor {
self.resultCode = "000001"
self.resultMsg = "请求数据失败"
}
if self.errorType == .notSuccessfulHTTP {
self.resultCode = "000001"
self.resultMsg = "网络错误,请稍后再试!"
}
if self.errorType == .noData {
self.resultCode = "没有相关业务数据返回"
}
if self.errorType == .notMakeObjectError {
self.resultCode = "解析Json失败"
}
}
}

请求接口

这里请求接口入参是T泛型。

1
2
3
4
5
6
7
8
9
10
11
12
/// 请求接口
///
/// - Parameter param: 请求参数
/// - Returns: Observable
public func request<T: ConvertToRequestParamable>(_ param: T, cache: HMCache = .none) -> Observable<Any>{
return rx_post(param.toRequestParam(), cache: cache)
}
public func requestParam(_ param: [String: Any], cache: HMCache = .none) -> Observable<Any>{
return rx_post(param, cache: cache)
}

请求处理和缓存处理

对于一个请求,有三种模式,第一种none:不用缓存,返回网络数据;第二种only:有缓存返回缓存,无缓存返回网络请求数据;第三种both:先返回缓存,再返回网络请求数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
extension HMSDK{
/// Rx Post 请求
///
/// - Parameter reqParams: 请求参数
/// - Returns: Observable
public func rx_post(_ reqParams: [String: Any], cache: HMCache = .none) -> Observable<Any> {
NSLog("┏…┅❉┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄❉…┅┓")
NSLog("┆ⓦⓔⓛⓒⓞⓜⓔTo ANDLINK ┆")
NSLog("┗…┅❉┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄❉…┅┛")
NSLog("〓")
NSLog("◥◤◢◣")
NSLog("〓----------------\(self.requestIndex)")
print("andlink-->请求参数:\n\( reqParams.printJson)\n")
return Observable<Any>
// .observeOn(SerialDispatchQueueScheduler.init(qos: .background))
.create { (subscriber) -> Disposable in
//self.operationQueue.maxConcurrentOperationCount = 5
guard self.token.characters.count != 0 else{
subscriber.onError(ANDLINKError.init(resultCode: "200003", resultMsg: "token令牌为空"))
return Disposables.create()
}
//拼接成为数据库的key
let reqJosn = JSON(reqParams)
let key = self.token + self.serviceURL + reqJosn["serviceName"].stringValue + reqJosn["methodName"].stringValue
let pre = NSPredicate(format: "key = %@",key)
if cache != .none {
//设置过滤条件
//建立Realm
do {
let realm = try RLMRealm.init(configuration: self.realmConfig)
// let realm = try! Realm()
// //过滤出来的数据(为数组)
// let ewresponse = realm.objects(ResultModel.self).filter(pre)
let ewresponse = ResultModel.objects(in: realm, with: pre)
// //先看有无缓存的话,如果有数据,数组即不为0
if ewresponse.count > 0 {
// //因为设置了过滤条件,只会出现一个数据,直接取
let filterResult: ResultModel = ewresponse[0] as! ResultModel
// //处理数据
self.response(data: filterResult.data, statusCode: filterResult.statuCode, key: key, subscriber: subscriber, local: true, cache: cache)
}
}catch let error{
subscriber.onError(error)
}
}
do {
self.requestIndex += 1
let opt = try HTTP.POST(self.serviceURL, parameters: reqParams, requestSerializer: JSONParameterSerializer())
opt.start { response in
// 记录当前请求索引
self.response(data: response.data, statusCode: response.statusCode, key: key, subscriber: subscriber, error: response.error, cache: cache)
}
//self.operationQueue.addOperation(opt)
} catch let error {
var responseParam = HMResponseParam()
let code = (error as NSError).code
responseParam.resultCode = String(code)
responseParam.resultMsg = error.localizedDescription
subscriber.onError(error)
}
return Disposables.create()
}
.observeOn(MainScheduler.init())
}
func response(data: Data?, statusCode: Int?, key: String, subscriber: AnyObserver<Any>, local: Bool = false, error: Error? = nil, cache: HMCache = .none){
if local == false {
if cache != .none {
//建立数据库模型并赋值
let model = ResultModel()
model.data = data
model.key = key
let timeDate = NSDate().string(withFormat: "yyyy年MM月dd日 hh:mm:ss")
model.time = timeDate
if statusCode != nil {
model.statuCode = statusCode!
}
DispatchQueue(label: "background").async {
autoreleasepool {
do {
let realm = try RLMRealm.init(configuration: self.realmConfig)
realm.beginWriteTransaction()
realm.addOrUpdate(model)
try! realm.commitWriteTransaction()
}catch let error {
print("RLMRealm-->addOrUpdate-->Error:\n\(error)")
}
}
}
}
}
if local && statusCode != 200 {
subscriber.onError(ANDLINKError(.notSuccessfulHTTP))
return
}
if (error != nil) {
var responseParam = HMResponseParam()
let code = (error! as NSError).code
responseParam.resultCode = String(code)
if code == -1009 {
subscriber.onError(ANDLINKError(.notSuccessfulHTTP))
}else if code == -1004{
subscriber.onError(ANDLINKError(.notSuccessfulHTTP))
}else{
responseParam.resultMsg = error?.localizedDescription
subscriber.onError(error!)
}
return
}
let json = JSON(data: data!)
if let printJosn = json.rawString(.utf8) {
if local == false {
print("andlink-->返回Json:\n\(printJosn)\n")
}else{
print("andlink(本地缓存)-->返回Json:\n\(printJosn)\n")
}
}
if json.type == .dictionary{
let responseParam = Mapper<HMResponseParam>().map(JSON: json.dictionaryObject!)!
if local == false {
print("andlink-->返回resultCode:\n"+responseParam.resultCode!+"\n")
print("andlink-->返回resultMsg:\n"+responseParam.resultMsg!+"\n")
}else{
print("andlink(本地缓存)-->返回resultCode:\n"+responseParam.resultCode!+"\n")
print("andlink(本地缓存)-->返回resultMsg:\n"+responseParam.resultMsg!+"\n")
}
if responseParam.resultCode == "000000"{
if (responseParam.data == nil){
if local == false {
print("andlink-->返回data为空\n")
}else{
print("andlink(本地缓存)-->返回data为空\n")
}
}else{
let jsonData = JSON(responseParam.data!)
if let printJosn = jsonData.rawString(.utf8) {
if local == false {
print("andlink-->返回data:\n\(printJosn)\n")
}else{
print("andlink(本地缓存)-->返回data:\n\(printJosn)\n")
}
}
}
subscriber.onNext(responseParam)
if local == false {
NSLog("╭⌒╮请求完成━┅~ ¤ ╭⌒╮ ╭⌒╮")
NSLog(" ╭⌒╭⌒╮╭⌒╮~╭⌒╮︶︶,︶︶")
NSLog(",︶︶︶︶,''︶~~ ,''~︶︶ ,''")
NSLog(" ╱◥█◣╱◥█◣")
NSLog(" ︱田︱田︱︱田︱田︱")
NSLog(" ╬╬╬╬╬╬╬╬╬╬╬╬╬╬")
subscriber.onCompleted()
}else{
if cache == .only {
subscriber.onCompleted()
}
}
}else{
subscriber.onError(ANDLINKError(resultCode: responseParam.resultCode, resultMsg: responseParam.resultMsg))
}
}
}
}

对返回的业务数据进行解析

对返回的业务数据Data进行解析,返回对于的Model,这个Moel也是T泛型。也可以返回相应对象的数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
extension Observable{
/// 解析JSON到Struct
///
/// - Parameter type: Model
/// - Returns: Observable
public func mapStruct<T: Mappable>(type: T.Type) -> Observable<T>{
return observeOn(SerialDispatchQueueScheduler.init(qos: .background))
.map({ representor in
guard let response = representor as? HMResponseParam else {
throw ANDLINKError(.noRepresentor)
}
if response.resultCode == "000000"{
return Mapper<T>().map(JSON: response.data! as! [String : Any])!
}else{
throw ANDLINKError(resultCode: response.resultCode, resultMsg: response.resultMsg)
}
})
.observeOn(MainScheduler.instance)
}
/// 解析JSON到Struct的数组
///
/// - Parameter type: Model
/// - Returns: Observable
public func mapArray<T: Mappable>(type: T.Type, key: String? = nil) -> Observable<[T]>{
return observeOn(SerialDispatchQueueScheduler.init(qos: .background))
.map({ representor in
guard let response = representor as? HMResponseParam else {
throw ANDLINKError(.noRepresentor)
}
if response.resultCode == "000000"{
guard (response.data != nil) else{
throw ANDLINKError(.noData)
}
// to array
let json = JSON(response.data!)
if json.type == .array {
return Mapper<T>().mapArray(JSONArray: json.arrayObject as! [[String : Any]])!
}
if json.type == .dictionary{
guard (key != nil) else {
let newKey = json.dictionary?.keys.first
return Mapper<T>().mapArray(JSONArray: json[newKey!].arrayObject as! [[String : Any]])!
}
return Mapper<T>().mapArray(JSONArray: json[key!].arrayObject as! [[String : Any]])!
}
throw ANDLINKError(.noData)
}else{
throw ANDLINKError(resultCode: response.resultCode, resultMsg: response.resultMsg)
}
})
.observeOn(MainScheduler.instance)
}
}

实例

获取设备列表

查看平台文档

将入参模型化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//
// HMDeviceListReqParam.swift
// BigHeMu
//
// Created by austin on 2017/4/25.
// Copyright © 2017年 BigHeMu. All rights reserved.
//
import Foundation
import ObjectMapper
/// 设备列表请求参数
struct HMDeviceListReqParam: ConvertToRequestParamable{
var deviceTypeId: String? // 设备类型Id。如果没有该参数,则查询所有类型的设备
var deviceId: String? // 设备id
var isRecursionQuery: Int? = 1 // 是否递归查询,1:否,0:是 递归查询表示查询满足条件的设备及其所有下级设备。
var familyId: String? // 家庭id
var page: Int? = 1 // 查询页数 不传默认为1
var pageSize: Int? = 100 // 每页显示的数据条数 不传默认为10
public init() {
}
public init?(map: Map) {
}
mutating func mapping(map: Map) {
deviceTypeId <- map["deviceTypeId"]
deviceId <- map["deviceId"]
isRecursionQuery <- map["isRecursionQuery"]
familyId <- map["familyId"]
page <- map["page"]
pageSize <- map["pageSize"]
}
public func toRequestParam() -> [String:Any]{
var reqParams = self.baseRequestParam()
reqParams.serviceName = HMServiceName.deviceManageService.rawValue
reqParams.methodName = HMMethodName.queryDeviceList4Page.rawValue
return reqParams.toJSON()
}
}

同样将设备信息模型化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//
// HMDeviceInfo.swift
// BigHeMu
//
// Created by austin on 2017/4/25.
// Copyright © 2017年 BigHeMu. All rights reserved.
//
import Foundation
import ObjectMapper
//MARK: - 设备信息
struct HMDeviceInfo: Mappable{
var MAC : String?
var appId : String?
var bindDeviceId : String?
var deviceIcon : String?
var deviceId : String?
var deviceModelCode : String?
var deviceModelId : String?
var deviceModelName : String?
var deviceName : String?
var deviceToken : String?
var deviceTypeId : String?
var deviceTypeName : String?
var electricity : Int?
var factoryId : String?
var factoryName : String?
var familyId : String?
var hasChildDevice : String?
var isUpgrade : Int?
var online : String?
var paramList : [HMDeviceParamList]?
var regTimeStr : String?
var sn : String?
var status : String?
public init(){
}
public init?(map: Map) {
}
mutating func mapping(map: Map) {
MAC <- map["MAC"]
appId <- map["appId"]
bindDeviceId <- map["bindDeviceId"]
deviceIcon <- map["deviceIcon"]
deviceId <- map["deviceId"]
deviceModelCode <- map["deviceModelCode"]
deviceModelId <- map["deviceModelId"]
deviceModelName <- map["deviceModelName"]
deviceName <- map["deviceName"]
deviceToken <- map["deviceToken"]
deviceTypeId <- map["deviceTypeId"]
deviceTypeName <- map["deviceTypeName"]
electricity <- map["electricity"]
factoryId <- map["factoryId"]
factoryName <- map["factoryName"]
familyId <- map["familyId"]
hasChildDevice <- map["hasChildDevice"]
isUpgrade <- map["isUpgrade"]
online <- map["online"]
paramList <- map["paramList"]
regTimeStr <- map["regTimeStr"]
sn <- map["sn"]
status <- map["status"]
}
}
struct HMDeviceParamList: Mappable{
/// 访问类型4:可读,2:可写,1:可执行,多选(如果多个则取二进制按位或运算)例如:6表示可读写
var accessType : Int?
var maxValue : String?
var minValue : String?
var paramCode : String?
var paramId : String?
var paramName : String?
var paramValueRange : [HMParamValue]?
/*
参数值范围类型。
0:表示minValue~maxValue之间的值有限可枚举,而且每一个值都有独立状态一一对应的,比如红灯,绿灯,黄灯;比如开,关。这时,对应的设备参数值范围表里,该参数的paramValue有值,而paramMinValue和paramMaxValue没有值
1:表示minValue~maxValue一系列连续值,且所有的值表示的同一个状态属性,比如温度,百分比等。这时,对应的设备参数值范围表里,没有该参数对应的数据。
2:参数的值对应的每一个状态,都是一个范围值。比如厂商用整数1-99表示震动的强度,数字越大代表震动强度越大。用1-30代表低震动状态,31-60代表中震动状态,61-80代表高震动状态,81-99超强震动状态。该例子只是举例说明,实际可能没有该情况。这时,对应的设备参数值范围表里,该参数的paramValue没有值,而paramMinValue和paramMaxValue有值
*/
var paramValueRangeType : String?
var type : Int?
var units : String?
var unitsName : String?
var value : String?
var valueTime : String?
var variable : Int?
public init(){
}
public init?(map: Map) {
}
mutating func mapping(map: Map) {
accessType <- map["accessType"]
maxValue <- map["maxValue"]
minValue <- map["minValue"]
paramCode <- map["paramCode"]
paramId <- map["paramId"]
paramName <- map["paramName"]
paramValueRange <- map["paramValueRange"]
paramValueRangeType <- map["paramValueRangeType"]
type <- map["type"]
units <- map["units"]
unitsName <- map["unitsName"]
value <- map["value"]
valueTime <- map["valueTime"]
variable <- map["variable"]
}
}
struct HMParamValue: Mappable{
var paramMaxValue : String?
var paramMinValue : String?
var paramValue : String?
var paramValueName : String?
var paramSelected : Bool = false
public init(){
}
public init?(map: Map) {
paramMaxValue <- map["paramMaxValue"]
paramMinValue <- map["paramMinValue"]
paramValue <- map["paramValue"]
paramValueName <- map["paramValueName"]
}
mutating func mapping(map: Map) {
}
}

例子:获取设备信息

1
2
3
4
5
6
7
8
9
10
11
/// 获取设备列表
func getDeivcesList(){
let deviceListReqParam = HMDeviceListReqParam()
andlink.request(deviceListReqParam, cache: .both)
.mapArray(type: HMDeviceInfo.self)
.subscribe(onNext: { (devices) in
print(devices)
}, onError: { (error) in
print(error)
}).addDisposableTo(disposeBag)
}

这样在业务层调用就很方便,使用起来就一个字,爽!!!

好了,到这里任务算是完成了。

总结

在编写过程中,难免有很多纰漏之处,望各路大神指点,若有任何问题都可以提出,愿接受各种批评和建议。觉得这篇对大家项目有用之处,可以给个评论,谢谢!