添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Swift网络请求(Moya篇)

在使用 Alamofire 进行网络请求的时候,相信大部分的同学都会封装一个抽象的NetworkLayer,如”APIManager” 或者 “NetworkModel”等等。但是位置业务功能增加,会渐渐混合各种请求,不够清晰,而Moya能很好地解决这类问题。Moya在Alamofire基础上进行封装,是一个允许高度自定义的网络层,可以根据具体的需求进行接口的设置。具体的介绍可以参考Moya的 官方链接 ,结构图如下:

接下来就介绍一下Moya的一些常见的用法:

(一)根据业务需求创建具体请求:

打比方现在我们需要书写账户的相关接口,如Login、userInfo。那么首先我们得创建AccountService:

1
2
3
4
enum AccountService {
case login(phoneNum: NSInteger,passWord: NSInteger)
case logout
}

然后让AccountService实现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
extension AccountService: TargetType {
var baseURL: URL {
return URL(string: ServiceBaseURL)!
}

var path: String {
switch self {
case .login(_, _):
return "accountService/login"
case .logout:
return "accountService/logout"
}
}

var method: Moya.Method {
switch self {
case .login(_, _):
return .post
case .logout:
return .get
}
}

var parameters: [String: Any]? {
switch self {
case .login(let phoneNum, let passWord):
return ["phoneNum": phoneNum, "passWord": passWord]
case .logout:
return nil
}
}

var parameterEncoding: ParameterEncoding {
return JSONEncoding.default // Send parameters as JSON in request body
}

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

var task: Task {
return .request
}

}

如上我们就已经完成了网络请求所需要的一个 endpoint 。接着通过Moya提供一个发送请求的 Provider就完成了基本的使用:

1
2
3
let provider = MoyaProvider<AccountService>()

provider.request(.login(phoneNum: 12345678901, passWord: 123456)) { result in
1
2
3
4
5
6
7
8
9
    switch result {
case let .success(response):
//...............
break
case let .failure(error):
//...............
break
}
}

(二)通过HTTPHeader设置公共请求参数

在实际开发中我们可能会需要在请求头内添加一些公共请求参数,如用于识别一些平台标志、辨别接口的版本号。你可以定义一个Endpoint的闭包,

1
2
3
4
5
let publicParamEndpointClosure = { (target: AccountService) -> Endpoint<AccountService> in
let url = target.baseURL.appendingPathComponent(target.path).absoluteString
let endpoint = Endpoint<AccountService>(url: url, sampleResponseClosure: { .networkResponse(200, target.sampleData) }, method: target.method, parameters: target.parameters, parameterEncoding: target.parameterEncoding)
return endpoint.adding(newHTTPHeaderFields: ["x-platform" : "iOS", "x-interface-version" : "1.0"])
}

然后在创建请求的 Provider把它添加上去,

1
let provider = MoyaProvider(endpointClosure: publicParamEndpointClosure)

(三)通过插件的方式监听网络状态

通常我们会在进行网络请求的时候进行一些状态展示,如loading,那么你可以通过插件的方式来实现。Moya默认有4个插件:

  • AccessTokenPlugin 管理AccessToken的插件
  • CredentialsPlugin 管理认证的插件
  • NetworkActivityPlugin 管理网络状态的插件
  • NetworkLoggerPlugin 管理网络log的插件
  • 在这里就演示一下NetworkActivityPlugin的使用:

    1
    2
    3
    4
    5
    6
    7
    8
    let networkPlugin = NetworkActivityPlugin { (type) in
    switch type {
    case .began:
    NSLog("显示loading")
    case .ended:
    NSLog("隐藏loading")
    }
    }

    同样在创建请求的 Provider把它添加上去即可

    1
    let provider = MoyaProvider<AccountService>(plugins: [networkPlugin])

    当然你也可以自定义一些功能的插件,只需要实现PluginType协议,具体功能实现可参考Moya默认的插件:

    1
    2
    3
    4
    5
    final class CustomPlugin: PluginType {

    // MARK: Plugin

    }

    (四)设置接口的超时时间

    一般网络的请求需要根据具体的业务接口设置合适的超时时间,你可以参照一下方法进行设置,

    1
    2
    3
    4
    5
    6
    7
    let requestTimeoutClosure = { (endpoint: Endpoint<AccountService>, done: @escaping MoyaProvider<AccountService>.RequestResultClosure) in

    guard var request = endpoint.urlRequest else { return }

    request.timeoutInterval = 30 //设置请求超时时间
    done(.success(request))
    }

    同样 在创建请求的Provider把它添加上去即可

    1
    let provider = MoyaProvider<AccountService>(requestClosure: requestTimeoutClosure)

    资料参考:

    http://www.jianshu.com/p/38fbc22a1e2b

    https://github.com/Moya/Moya

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置: jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true