扬庆の博客

Moya(3) 开发应用篇1

字数统计: 973阅读时长: 4 min
2021/03/23 Share

开发中如何用 Moya

一步一步的,从基础到优雅的使用

一般情况 , 写界面代码如下面

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
	override func viewDidLoad() {
super.viewDidLoad()

setupUI()
binding()
}

func setupUI() {
nameLabel.font = UIFont.systemFont(ofSize: 14)
nameLabel.textColor = UIColor.red
ageLabel.font = UIFont.systemFont(ofSize: 14)
view.addSubview(nameLabel)
view.addSubview(ageLabel)

nameLabel.snp.makeConstraints { (make) in
make.top.left.right.equalTo(25)
make.height.equalTo(30)
}
ageLabel.snp.makeConstraints { (make) in
make.left.right.equalTo(nameLabel)
make.top.equalTo(nameLabel.snp.bottom).offset(10)
make.height.equalTo(30)
}
}

// 下面用一个 moya 网路请求关联数据到控件

所需数据模型 MyService

1
2
3
4
struct MyServiceModel: HandyJSON {
var name: String = ""
var age: String = ""
}

新建一个MyServiceTarget 文件 , 里面建一个 MyServiceTarget 枚举, 扩展这个枚举继承协议TargetType 并实现接口请求所需的参数等信息

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
import Foundation
import Moya
import HandyJSON

enum MyServiceTarget {
case login(
userAccount: String,
password: String
)

case findPassword(
password: String,
updatePasswordToken: String
)
}

extension MyServiceTarget: TargetType {
var baseURL: URL {
return URL(string: "https://www.baidu.com")!
}

var path: String {
return "s?cl=3&tn=baidutop10&fr=top1000&wd=外交部召见欧盟驻华代表团团长&rsv_idx=2&rsv_dl=fyb_n_homepage&hisfilter=1"
}

var method: Moya.Method {
return .post
}

var sampleData: Data {
return "".data(using: .utf8)!
}


var parameters: [String : Any]? {
switch self {
case .login(let userAccount, let password):
return [
"userAccount":userAccount,
"password":password
]
case .findPassword(let password, let updatePasswordToken):
return ["password":password,"updatePasswordToken":updatePasswordToken]
}
}

var task: Task {
let params = parameters ?? [:]

return .requestParameters(parameters: params, encoding: JSONEncoding.default)
}

var headers: [String : String]? { return nil }



}

到这里 请求所需的信息都已经好了,下面开始界面请求接口 , 获取age , name 这两个信息

网络请求数据

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
// Simulate a network request
let provider = MoyaProvider<MyServiceTarget>.appearance()

// Send request
provider.request(.login(userAccount: "18516635543", password: "1234565")
) { (response) in
switch response {
case .success(let resp):

// 解析 json: json 可能包含 Data的数据类型;
// 也可能只是状态码的返回类型
let baseDataResult = self.mapModel(resp: resp)
// 处理返回的 moyaResult
switch baseDataResult {
case .success(let md):

/*匹配界面UI数据*/
self.nameLabel.text = md.name
self.ageLabel.text = md.age

case .failure(_, let errorMsg):
print(errorMsg) // 处理失败信息
}
return
case .failure(_):
// 无网络
print("网络异常, 请检查")
return
}
}

里面可以看到 provider 调用 request 的返回数据 要去解析数据 json 格式 转换为我们的 MyServiceModel

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
// 取出来一个转解析response 的方法, 想办法转成我们想要的 JSON
func mapModel(resp: Response) -> MoyaResult<MyServiceModel> {
// 1.过滤状态码
guard let _ = try? resp.filterSuccessfulStatusCodes() else {
return .failure(resp.statusCode, "服务器访问失败")
}

// 下面就是服务器返回的数据的问题了
// 2.解析 json
// 转换成 jsonString
// Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable.
// the resulting data is a encoded in UTF-8.
// Setting the NSJSONReadingMutableLeaves option will make the parser generate mutable NSString objects.

guard let jsonObj = try? JSONSerialization.jsonObject(with: resp.data, options: JSONSerialization.ReadingOptions.mutableLeaves),

let jsonData = try? JSONSerialization.data(withJSONObject: jsonObj, options: JSONSerialization.WritingOptions.prettyPrinted),

let jsonString = String(data: jsonData, encoding: String.Encoding.utf8) else{
return .failure(-1, "数据无效")
}

// 打印 json 字符串
print(jsonString)
// 3.json 转 model
guard let base = JSONDeserializer<BaseData<MyServiceModel>>.deserializeFrom(json: jsonString) else {
return .failure(-1, "数据无效")
}

/*
转换数据格式分为两种:
1. 无数据,只是表示成功或者失败状态
2. 有数据,返回 0.model 1.只有状态码,和描述字符串
*/
// 1. No model data, only status information
if base.errcode == 0 {
// valid model data success
if let data = base.data {
return .success(data)
}
return .failure(-1, "数据无效")
}else {
// return valid data, but data is other status
return .failure(base.errcode, base.errmsg)
}
}

到这里 Moya 关于一个数据请求, 所有的步骤都包含了 , 并且拿到服务器返回的数据, 解析到控件上进行显示

思考🤔: 每个界面都有一个或者多个请求 API, 一个项目又有多个界面组成

How do you do?

未完待续 ….

1. Moya 基本概念

2. Moya 和 Alamofire 关系

3. Moya 开发应用篇 1

4. Moya 开发应用篇 2

5. Moya 开发应用篇 3

CATALOG
  1. 1. 开发中如何用 Moya
    1. 1.0.0.1. 到这里 请求所需的信息都已经好了,下面开始界面请求接口 , 获取age , name 这两个信息
  2. 1.0.1. 思考🤔: 每个界面都有一个或者多个请求 API, 一个项目又有多个界面组成