swift 网络请求
使用moya框架
pod 'Moya', '~> 15.0'
# handyjson 处理数据
pod 'HandyJSON', '5.0.3-beta'
1
2
3
4
定义一个BaseAPI
import Moya
private var BASEURL = "www.baidu.com"
class BaseAPI {
let requestBaseUrl = BASEURL
var requestCommenParam: [String: Any] {
get {
return [:]
}
}
var requestHeader: [String: String]? {
get {
return ["Content-Type": "text/plain", "charset": "utf-8"]
}
}
var requestTimeOut = 30.0
}
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
定义自己的项目api继承baseApi
class DemoAPI: BaseAPI {
var requestPath: String?
var requestParam: [String: Any]?
var requestMethod: Moya.Method = .get
}
extension DemoAPI : TargetType {
var baseURL: URL { return URL(string: requestBaseUrl)! }
var path: String {
guard let requestPath = requestPath else { return "" }
return requestPath
}
var method: Moya.Method {
return requestMethod
}
var task: Task {
var param: [String: Any] = [:]
param.merge(requestCommenParam) { return $1 }
if let requestParam = requestParam {
param.merge(requestParam) { return $1 }
}
return .requestParameters(parameters: param, encoding: URLEncoding.default)
}
var headers: [String : String]? {
return requestHeader
}
}
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
定义一个请求管理器
import Moya
import HandyJSON
class DemoRequestManager {
static func DemoRequestModule<T: HandyJSON>(path: String, method: Moya.Method = .get, param: [String: Any]?, done: @escaping ((_ succeed: Bool, _ data: T?) -> Void)) {
let api = RosettaAPI()
api.requestPath = path
api.requestParam = param
api.requestMethod = method
let timeoutClosure = { (endpoint: Endpoint, done: @escaping MoyaProvider<RosettaAPI>.RequestResultClosure) in
do {
var request = try endpoint.urlRequest()
request.timeoutInterval = api.requestTimeOut
done(.success(request))
} catch {
return
}
}
let provider = MoyaProvider<RosettaAPI>(requestClosure: timeoutClosure)
provider.request(api) { result in
self.handleResult(result: result, done:done)
}
}
private static func handleResult<T: HandyJSON>(result:Result<Moya.Response, MoyaError>, done: @escaping ((_ succeed: Bool, _ data: T?) -> Void)){
switch result {
case .success(let response):
let dic = try? response.mapJSON() as? Dictionary<String, Any>
let value = T.deserialize(from: dic)
if let result = T.deserialize(from: dic) {
done(true, result)
} else {
done(false, nil)
}
if let request = response.request,
let method = request.method,
let json = String(data: response.data, encoding: .utf8){
print("~~~~~~~~~~~Request Start~~~~~~~~~~~~")
print("Method:\(method.rawValue)\nURL:\(request)\nBody:\(String(describing: request.httpBody))\nResult:\n\(json)")
print("~~~~~~~~~~~Request End~~~~~~~~~~~~")
}
case .failure(let error):
print(error)
done(false, nil)
}
}
}
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
比如请求一个banner
enum HomeApi: String {
case banner = "/cms/banner"
}
extension DemoRequestManager {
static func getBanner(param: [String: Any]?, done: @escaping (_ succeed: Bool ,_ data: BannerModels?) -> Void) {
DemoRequestModule(path: HomeApi.banner.rawValue, method: .get, param: param, done: done)
}
}
# model 代码
import HandyJSON
struct BannerModel : HandyJSON {
var id: Int?
var name: String?
var imagePath: String?
}
struct BannerModels :HandyJSON {
var obj: [BannerModel]?
var success: Bool?
var msg:String?
var code: String?
var version:String?
var size: Int?
}
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
swift webscoket链接
private let urlSession = URLSession(configuration: .default)
private var webSocketTask: URLSessionWebSocketTask?
private let baseURL = URL(string: BaseWsApi.binance.rawValue)!
func connect() {
stop()
webSocketTask = urlSession.webSocketTask(with: baseURL)
webSocketTask?.resume()
receiveMessage()
}
func stop() {
webSocketTask?.cancel(with: .goingAway, reason: nil)
}
private func sendMessage(symbolPair:String)
{
var subTicker:TickerSubModel = TickerSubModel()
subTicker.params?.append(symbolPair + "@ticker")
do {
let jsonData = try JSONEncoder().encode(subTicker)
let subString = String(decoding: jsonData, as: UTF8.self)
print(subString)
let message = URLSessionWebSocketTask.Message.string(subString)
webSocketTask?.send(message) { error in
if let error = error {
print("WebSocket couldn’t send message because: \(error)")
}
}
} catch {
print(error.localizedDescription)
}
}
private func receiveMessage() {
webSocketTask?.receive {[weak self] result in
switch result {
case .failure(let error):
print("Error in receiving message: \(error)")
case .success(.string(let str)):
do {
let bmodel = try JSONDecoder().decode(BinanceTickerModel.self, from: Data(str.utf8))
DispatchQueue.main.async{
self?.addMarket(bmodel: bmodel)
}
} catch {
print("error is \(error.localizedDescription)")
}
self?.receiveMessage()
default:
print("default")
}
}
}
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
swift 原生codeable 解析到不存在的值 为nil,想要赋默认值时需要扩展jsondecoder
extension KeyedDecodingContainer {
public func decodeIfPresent(_ type: Bool.Type, forKey key: K) throws -> Bool? {
if let value = try? decode(type, forKey: key) {
return value
}
return false
}
public func decodeIfPresent(_ type: Int.Type, forKey key: K) throws -> Int? {
if let value = try? decode(type, forKey: key) {
return value
}
return 0
}
public func decodeIfPresent(_ type: String.Type, forKey key: K) throws -> String? {
if let value = try? decode(type, forKey: key) {
return value
}
return ""
}
}
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
swift moya async + await 请求