Browse Source

网络请求优化/数据解析处理

首页图标修改
main
sunyufeng 1 year ago
parent
commit
b1cf321086

+ 23
- 0
iOSFirst/Assets.xcassets/ic_person.imageset/Contents.json View File

1
+{
2
+  "images" : [
3
+    {
4
+      "filename" : "toux.png",
5
+      "idiom" : "universal",
6
+      "scale" : "1x"
7
+    },
8
+    {
9
+      "filename" : "toux@2x.png",
10
+      "idiom" : "universal",
11
+      "scale" : "2x"
12
+    },
13
+    {
14
+      "filename" : "toux@3x.png",
15
+      "idiom" : "universal",
16
+      "scale" : "3x"
17
+    }
18
+  ],
19
+  "info" : {
20
+    "author" : "xcode",
21
+    "version" : 1
22
+  }
23
+}

BIN
iOSFirst/Assets.xcassets/ic_person.imageset/toux.png View File


BIN
iOSFirst/Assets.xcassets/ic_person.imageset/toux@2x.png View File


BIN
iOSFirst/Assets.xcassets/ic_person.imageset/toux@3x.png View File


+ 23
- 0
iOSFirst/Assets.xcassets/ic_pwd.imageset/Contents.json View File

1
+{
2
+  "images" : [
3
+    {
4
+      "filename" : "密码 (1).png",
5
+      "idiom" : "universal",
6
+      "scale" : "1x"
7
+    },
8
+    {
9
+      "filename" : "密码 (1)@2x.png",
10
+      "idiom" : "universal",
11
+      "scale" : "2x"
12
+    },
13
+    {
14
+      "filename" : "密码 (1)@3x.png",
15
+      "idiom" : "universal",
16
+      "scale" : "3x"
17
+    }
18
+  ],
19
+  "info" : {
20
+    "author" : "xcode",
21
+    "version" : 1
22
+  }
23
+}

BIN
iOSFirst/Assets.xcassets/ic_pwd.imageset/密码 (1).png View File


BIN
iOSFirst/Assets.xcassets/ic_pwd.imageset/密码 (1)@2x.png View File


BIN
iOSFirst/Assets.xcassets/ic_pwd.imageset/密码 (1)@3x.png View File


+ 23
- 0
iOSFirst/Assets.xcassets/ic_setting.imageset/Contents.json View File

1
+{
2
+  "images" : [
3
+    {
4
+      "filename" : "筛选.png",
5
+      "idiom" : "universal",
6
+      "scale" : "1x"
7
+    },
8
+    {
9
+      "filename" : "筛选@2x.png",
10
+      "idiom" : "universal",
11
+      "scale" : "2x"
12
+    },
13
+    {
14
+      "filename" : "筛选@3x.png",
15
+      "idiom" : "universal",
16
+      "scale" : "3x"
17
+    }
18
+  ],
19
+  "info" : {
20
+    "author" : "xcode",
21
+    "version" : 1
22
+  }
23
+}

BIN
iOSFirst/Assets.xcassets/ic_setting.imageset/筛选.png View File


BIN
iOSFirst/Assets.xcassets/ic_setting.imageset/筛选@2x.png View File


BIN
iOSFirst/Assets.xcassets/ic_setting.imageset/筛选@3x.png View File


+ 17
- 7
iOSFirst/login/LoginView.swift View File

17
     @State private var isPresent:Bool = false
17
     @State private var isPresent:Bool = false
18
     @State private var checked:Bool = true
18
     @State private var checked:Bool = true
19
     @State private var inputPasswordMessage:String = ""
19
     @State private var inputPasswordMessage:String = ""
20
+    @Environment(\.presentationMode) var presentationMode;
21
+
20
     
22
     
21
     var body: some View {
23
     var body: some View {
22
-        
23
         VStack(alignment:.leading,spacing: 0) {
24
         VStack(alignment:.leading,spacing: 0) {
24
             HStack{
25
             HStack{
25
                 Spacer()
26
                 Spacer()
26
-                Image(systemName: "globe")
27
+                Image("ic_setting")
27
                     .imageScale(.large)
28
                     .imageScale(.large)
28
                     .foregroundColor(.accentColor)
29
                     .foregroundColor(.accentColor)
29
                 Text("设置").font(.system(size: 14))
30
                 Text("设置").font(.system(size: 14))
55
             
56
             
56
             VStack(alignment: .leading, spacing: 400) {
57
             VStack(alignment: .leading, spacing: 400) {
57
                 HStack(alignment: .center, spacing: 15) {
58
                 HStack(alignment: .center, spacing: 15) {
58
-                    Image(systemName: "globe")
59
+                    Image("ic_person")
59
                         .imageScale(.large)
60
                         .imageScale(.large)
60
                         .foregroundColor(.accentColor)
61
                         .foregroundColor(.accentColor)
61
                     
62
                     
72
             Divider()
73
             Divider()
73
             VStack(alignment: .leading, spacing: 400) {
74
             VStack(alignment: .leading, spacing: 400) {
74
                 HStack(alignment: .center, spacing: 15) {
75
                 HStack(alignment: .center, spacing: 15) {
75
-                    Image(systemName: "globe")
76
+                    Image("ic_pwd")
76
                         .imageScale(.large)
77
                         .imageScale(.large)
77
                         .foregroundColor(.accentColor)
78
                         .foregroundColor(.accentColor)
78
                     
79
                     
86
                 }
87
                 }
87
                 
88
                 
88
             }.frame(height: 80)
89
             }.frame(height: 80)
89
-            Divider().padding(.bottom,40)
90
+            Divider().padding(.bottom,20)
90
             
91
             
91
             
92
             
92
             VStack(alignment: .trailing, spacing: 400) {
93
             VStack(alignment: .trailing, spacing: 400) {
102
                             .font(.system(size: 15))
103
                             .font(.system(size: 15))
103
                         Spacer()
104
                         Spacer()
104
                     }
105
                     }
106
+                    Spacer().frame(height: 15)
105
                     Button(action: {
107
                     Button(action: {
106
                         if(inputAccountMessage.isEmpty){
108
                         if(inputAccountMessage.isEmpty){
107
                             SUIToast.show(messageItem: .init(
109
                             SUIToast.show(messageItem: .init(
117
                             ))
119
                             ))
118
                         }else {
120
                         }else {
119
                             viewModel.loginUser(username: inputAccountMessage, password: inputPasswordMessage)
121
                             viewModel.loginUser(username: inputAccountMessage, password: inputPasswordMessage)
120
-                            isPresent=true
122
+                            if (!viewModel.userResponse.hasObservers){
123
+                                viewModel.userResponse.subscribe { event in
124
+                                    isPresent=true
125
+                                    print("接收到的token值\(String(describing: event.element?.token_value))")
126
+                                    // 这里需要返回首页,登陆成功后销毁本页面
127
+                                    self.presentationMode.wrappedValue.dismiss()
128
+                                }
129
+                                
130
+                            }
121
                         }
131
                         }
122
                         
132
                         
123
-                    }) {
133
+                    }){
124
                         Text("登录")
134
                         Text("登录")
125
                             .font(.system(size: 17))
135
                             .font(.system(size: 17))
126
                             .bold()
136
                             .bold()

+ 10
- 19
iOSFirst/login/LoginViewModel.swift View File

10
 import RxSwift
10
 import RxSwift
11
 import RxCocoa
11
 import RxCocoa
12
 import RxRelay
12
 import RxRelay
13
+import SwiftyJSON
14
+import HandyJSON
13
 
15
 
14
 
16
 
15
 class LoginViewModel  {
17
 class LoginViewModel  {
16
     
18
     
17
-    private let service:MoyaProvider<AccountService>
18
     private var bag = DisposeBag()
19
     private var bag = DisposeBag()
19
     var userResponse = PublishSubject<LoginUserInfo>()
20
     var userResponse = PublishSubject<LoginUserInfo>()
20
     
21
     
21
-    init(service:MoyaProvider<AccountService> = accountProvider) {
22
-        self.service = service
23
-        
24
-    }
25
     
22
     
26
     
23
     
27
     func loginUser(username:String,password:String) {
24
     func loginUser(username:String,password:String) {
28
-        service.rx.request(.login(username, password,false)).subscribe { [weak self] event in
29
-            switch event {
30
-            case let .success(response):
31
-                do {
32
-                    let response = try response.mapString()
33
-                    log.info( response )
34
-                    
35
-                } catch let error {
36
-                    log.error(error.localizedDescription)
37
-                }
38
-            case .failure(let error):
39
-                log.error(error.localizedDescription)
25
+        NetworkManaer
26
+            .request(AccountService.login(username, password, false)) {[weak self] json in
27
+                //            self?.mTextView.text = String(describing: JSON(json))
28
+                self?.userResponse.onNext(json)
29
+
30
+            } failure: {code, msg in
31
+                log.info("code : \(code!)")
32
+                log.info("message : \(msg)")
40
             }
33
             }
41
-        }.disposed(by: bag)
42
-        
43
     }
34
     }
44
     
35
     
45
 }
36
 }

+ 23
- 0
iOSFirst/network/BaseResponse.swift View File

1
+//
2
+//  BaseResponse.swift
3
+//  iOSFirst
4
+//
5
+//  Created by 孙宇峰 on 2023/2/24.
6
+//
7
+
8
+import Foundation
9
+import HandyJSON
10
+ struct  BaseResponse<T:HandyJSON>: HandyJSON{
11
+    
12
+    
13
+    //用户表
14
+    var code:Int?
15
+    
16
+    //姓名
17
+    var msg:String?
18
+    
19
+    //登录帐号
20
+    var  data:T?
21
+
22
+
23
+}

+ 108
- 33
iOSFirst/network/NetworkManager.swift View File

8
 import Foundation
8
 import Foundation
9
 import Moya
9
 import Moya
10
 import Alamofire
10
 import Alamofire
11
+import HandyJSON
12
+import RxSwift
11
 import SwiftyJSON
13
 import SwiftyJSON
12
 
14
 
13
 /// 超时时长
15
 /// 超时时长
14
 private var requestTimeOut:Double = 30
16
 private var requestTimeOut:Double = 30
15
 ///endpointClosure
17
 ///endpointClosure
16
-private let myEndpointClosure = { (target: AccountService) -> Endpoint in
17
-///这里的endpointClosure和网上其他实现有些不太一样。
18
-///主要是为了解决URL带有?无法请求正确的链接地址的bug
18
+public let myEndpointClosure = { (target: TargetType) -> Endpoint in
19
+    ///这里的endpointClosure和网上其他实现有些不太一样。
20
+    ///主要是为了解决URL带有?无法请求正确的链接地址的bug
19
     let url = target.baseURL.absoluteString + target.path
21
     let url = target.baseURL.absoluteString + target.path
20
     var endpoint = Endpoint(
22
     var endpoint = Endpoint(
21
         url: url,
23
         url: url,
31
     }
33
     }
32
 }
34
 }
33
 
35
 
34
-private let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
36
+public let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
35
     do {
37
     do {
36
         var request = try endpoint.urlRequest()
38
         var request = try endpoint.urlRequest()
37
         //设置请求时长
39
         //设置请求时长
42
         }else{
44
         }else{
43
             log.info("\(request.url!)"+"\(String(describing: request.httpMethod))")
45
             log.info("\(request.url!)"+"\(String(describing: request.httpMethod))")
44
         }
46
         }
47
+        if let header = request.allHTTPHeaderFields {
48
+            log.info("请求头内容\(header)")
49
+        }
45
         done(.success(request))
50
         done(.success(request))
46
     } catch {
51
     } catch {
47
         done(.failure(MoyaError.underlying(error, nil)))
52
         done(.failure(MoyaError.underlying(error, nil)))
48
     }
53
     }
49
 }
54
 }
50
 
55
 
51
-/*   设置ssl
52
-let policies: [String: ServerTrustPolicy] = [
53
-    "example.com": .pinPublicKeys(
54
-        publicKeys: ServerTrustPolicy.publicKeysInBundle(),
55
-        validateCertificateChain: true,
56
-        validateHost: true
57
-    )
58
-]
59
-*/
60
-
61
-// 用Moya默认的Manager还是Alamofire的Manager看实际需求。HTTPS就要手动实现Manager了
62
-//private public func defaultAlamofireManager() -> Manager {
63
-//
64
-//    let configuration = URLSessionConfiguration.default
65
-//
66
-//    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
67
-//
68
-//    let policies: [String: ServerTrustPolicy] = [
69
-//        "ap.grtstar.cn": .disableEvaluation
70
-//    ]
71
-//    let manager = Alamofire.SessionManager(configuration: configuration,serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies))
72
-//
73
-//    manager.startRequestsImmediately = false
74
-//
75
-//    return manager
76
-//}
77
-
78
 
56
 
79
 /// NetworkActivityPlugin插件用来监听网络请求
57
 /// NetworkActivityPlugin插件用来监听网络请求
80
-private let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
81
-
58
+public let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
59
+    
82
     log.info("networkPlugin \(changeType)")
60
     log.info("networkPlugin \(changeType)")
83
     //targetType 是当前请求的基本信息
61
     //targetType 是当前请求的基本信息
84
     switch(changeType){
62
     switch(changeType){
90
     }
68
     }
91
 }
69
 }
92
 
70
 
71
+
93
 // https://github.com/Moya/Moya/blob/master/docs/Providers.md  参数使用说明
72
 // https://github.com/Moya/Moya/blob/master/docs/Providers.md  参数使用说明
94
 //stubClosure   用来延时发送网络请求
73
 //stubClosure   用来延时发送网络请求
95
 
74
 
75
+final class TdwMoyaPlugin: PluginType {
76
+    
77
+    public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
78
+        var request = request
79
+        request.addValue("token值", forHTTPHeaderField: "token名字")
80
+        return request
81
+    }
82
+}
83
+
84
+
85
+
96
 let accountProvider = MoyaProvider<AccountService>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
86
 let accountProvider = MoyaProvider<AccountService>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
87
+
88
+public class NetworkManaer{
89
+    
90
+    
91
+    /// 使用Moya的请求封装
92
+    ///
93
+    /// - Parameters:
94
+    ///   - target: 请求API,TargetType里的枚举值
95
+    ///   - success: 成功的回调
96
+    ///   - error: 连接服务器成功但是数据获取失败
97
+    ///   - failure: 连接服务器失败
98
+    public class func request<T: TargetType,U: HandyJSON>(_ target: T, success: @escaping((U) -> Void), failure: ((Int?, String) ->Void)?) {
99
+        let provider = MoyaProvider<T>(
100
+            endpointClosure: myEndpointClosure,
101
+            requestClosure: requestClosure,
102
+            plugins: [networkPlugin],
103
+            trackInflights: false
104
+            //            networkLoggerPlugin
105
+        )
106
+        
107
+        provider.request(target) { result in
108
+            switch result {
109
+            case let .success(response):
110
+                //                let json = try? response.mapString()
111
+                //                let responseObject = try? response.mapJSON()
112
+                //                JhLog( responseObject ?? "" );
113
+                do {
114
+                    // *********** 这里可以统一处理错误码,弹出提示信息 ***********
115
+                    let resObject = try? response.mapJSON()
116
+                    let responseObject = JSON(resObject ?? "")
117
+                    let code = responseObject["code"].intValue
118
+                    let msg = String(describing: responseObject["msg"])
119
+                    switch (code) {
120
+                    case 0 :
121
+                        let dictionary=responseObject["obj"].dictionaryObject
122
+                        let responseData=U.deserialize(from: dictionary)
123
+                        log.info(responseData?.toJSONString())
124
+                        // 数据返回正确
125
+                        success(responseData!)
126
+                    case 2:
127
+                        // 请重新登录
128
+                        failure!(code,msg)
129
+                        alertLogin(msg)
130
+                    default:
131
+                        // 其他错误
132
+                        failureHandle(failure: failure, stateCode: code, message: msg)
133
+                    }
134
+                }
135
+            case let .failure(error):
136
+                let statusCode = error.response?.statusCode ?? 1000
137
+                let message = "请求出错,错误码:" + String(statusCode)
138
+                log.error(message)
139
+                failureHandle(failure: failure, stateCode: statusCode, message: error.errorDescription ?? message)
140
+            }
141
+        }
142
+        
143
+        // 错误处理 - 弹出错误信息
144
+        func failureHandle(failure: ((Int?, String) ->Void)? , stateCode: Int?, message: String) {
145
+//            Alert.show(type: .error, text: message)
146
+            //弹出错误信息
147
+            failure?(stateCode ,message)
148
+        }
149
+        
150
+        // 登录弹窗 - 弹出是否需要登录的窗口
151
+        func alertLogin(_ title: String?) {
152
+            // TODO: 跳转到登录页的操作:
153
+        }
154
+        
155
+    }
156
+    
157
+    // MARK: - 打印日志
158
+    //    static let networkLoggerPlugin = NetworkLoggerPlugin(verbose: true, cURL: true, requestDataFormatter: { data -> String in
159
+    //        return String(data: data, encoding: .utf8) ?? ""
160
+    //    }) { data -> (Data) in
161
+    //        do {
162
+    //            let dataAsJSON = try JSONSerialization.jsonObject(with: data)
163
+    //            let prettyData =  try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
164
+    //            return prettyData
165
+    //        } catch {
166
+    //            return data
167
+    //        }
168
+    //    }
169
+}
170
+
171
+

Loading…
Cancel
Save