Browse Source

网络请求 登录信息 登录状态保存

根据登录状态处理header逻辑等
AES 加解密(iOS与Android 以及后台不一致)
main
sunyufeng 1 year ago
parent
commit
81d6840d57

+ 2
- 1
Podfile View File

@@ -33,7 +33,8 @@ target 'iOSFirst' do
33 33
   pod 'SVProgressHUD'
34 34
   #播放网络音频
35 35
   pod 'StreamingKit'
36
-  pod 'RxNetworks'
36
+  #加密解密工具
37
+  pod 'CryptoSwift', '~> 1.6.0'
37 38
   #pod 'Toast-Swift', '~> 5.0.1'
38 39
  #target 'iOSFirstTests' do
39 40
     #inherit! :search_paths

+ 1
- 1
iOSFirst.xcodeproj/xcuserdata/sunyufeng.xcuserdatad/xcschemes/xcschememanagement.plist View File

@@ -7,7 +7,7 @@
7 7
 		<key>iOSFirst.xcscheme_^#shared#^_</key>
8 8
 		<dict>
9 9
 			<key>orderHint</key>
10
-			<integer>23</integer>
10
+			<integer>20</integer>
11 11
 		</dict>
12 12
 	</dict>
13 13
 </dict>

+ 1
- 0
iOSFirst/iOSFirstApp.swift View File

@@ -6,6 +6,7 @@
6 6
 //
7 7
 
8 8
 import SwiftUI
9
+let isDebug = true
9 10
 
10 11
 class AppDelegate: NSObject, UIApplicationDelegate {
11 12
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

+ 176
- 97
iOSFirst/login/LoginUserInfo.swift View File

@@ -8,104 +8,183 @@
8 8
 import Foundation
9 9
 import HandyJSON
10 10
 
11
-class LoginUserInfo: HandyJSON{
11
+class LoginUserInfo: NSObject, NSCoding,HandyJSON{
12 12
     
13
-        //用户表
14
-        var userid:Int?
15
-        
16
-        //姓名
17
-        var username:String?
18
-        
19
-        //登录帐号
20
-        var  loginname:String?
21
-        
22
-        //登录密码
23
-        var  loginpwd:String?
24
-        
25
-        //学生学号
26
-        var  studentno:String?
27
-        
28
-        //用户手机号
29
-        var  userphone:String?
30
-        
31
-        //出生日期
32
-        var  userbirthday:Int?
33
-        
34
-        //身份证号
35
-        var  cardid:String?
36
-        
37
-        //头像地址
38
-        var  headpic:String?
39
-        
40
-        //用户类型999超级管理员0学校管理员1老师2学生
41
-        var  usertype:Int?
42
-        
43
-        //用户状态1正常2删除
44
-        var  userstate:Int?
45
-        
46
-        //是否绑定硬件地址0不绑定1绑定
47
-        var  bindmac:Int?
48
-        
49
-        //硬件地址
50
-        var  mac:String?
51
-        
52
-        //硬件地址绑定的帐号
53
-        var  macname:String?
54
-        
55
-        //学校是否绑定硬件地址0不绑定1绑定
56
-        var  sbindmac:Int?
57
-        
58
-        //操作密码(教师操作密码)
59
-        var  opepassword:String?
60
-        
61
-        //创建人id
62
-        var  createid:Int?
63
-        
64
-        //创建人姓名
65
-        var  createname:String?
66
-        
67
-        //创建时间
68
-        var  createtime:Int?
69
-        
70
-        //删除人id
71
-        var  deleteid:Int?
72
-        
73
-        //删除时间
74
-        var  deletetime:Int?
75
-        
76
-        //学校id
77
-        var  schoolid:Int?
78
-        
79
-        var  schoolname:String?
80
-        
81
-        //学校阶段1小学2初中3高中4大学
82
-        var  schoollevel:Int?
83
-        
84
-        //学校状态1正常10删除
85
-        var  schoolstate:Int?
86
-        
87
-        //错误率%
88
-        var  errorrate:Int?
89
-        
90
-        //当前年份
91
-        var  year:Int?
92
-        
93
-        //性别1男2女
94
-        var  usersex:Int?
95
-        
96
-        //区域码
97
-        var  cloudcode:String?
98
-        
99
-        //班级id
100
-        var  classid:Int?
101
-        
102
-        //
103
-        var  xznum:Int?
104
-
105
-        // token
106
-        var  token_value:String?
107 13
     
108
-        required init(){}
109
-
14
+    required override init() {}
15
+    
16
+    
17
+    //用户表
18
+    var userid:Int?
19
+    
20
+    //姓名
21
+    var username:String?
22
+    
23
+    //登录帐号
24
+    var  loginname:String?
25
+    
26
+    //登录密码
27
+    var  loginpwd:String?
28
+    
29
+    //学生学号
30
+    var  studentno:String?
31
+    
32
+    //用户手机号
33
+    var  userphone:String?
34
+    
35
+    //出生日期
36
+    var  userbirthday:Int?
37
+    
38
+    //身份证号
39
+    var  cardid:String?
40
+    
41
+    //头像地址
42
+    var  headpic:String?
43
+    
44
+    //用户类型999超级管理员0学校管理员1老师2学生
45
+    var  usertype:Int?
46
+    
47
+    //用户状态1正常2删除
48
+    var  userstate:Int?
49
+    
50
+    //是否绑定硬件地址0不绑定1绑定
51
+    var  bindmac:Int?
52
+    
53
+    //硬件地址
54
+    var  mac:String?
55
+    
56
+    //硬件地址绑定的帐号
57
+    var  macname:String?
58
+    
59
+    //学校是否绑定硬件地址0不绑定1绑定
60
+    var  sbindmac:Int?
61
+    
62
+    //操作密码(教师操作密码)
63
+    var  opepassword:String?
64
+    
65
+    //创建人id
66
+    var  createid:Int?
67
+    
68
+    //创建人姓名
69
+    var  createname:String?
70
+    
71
+    //创建时间
72
+    var  createtime:Int?
73
+    
74
+    //删除人id
75
+    var  deleteid:Int?
76
+    
77
+    //删除时间
78
+    var  deletetime:Int?
79
+    
80
+    //学校id
81
+    var  schoolid:Int?
82
+    
83
+    var  schoolname:String?
84
+    
85
+    //学校阶段1小学2初中3高中4大学
86
+    var  schoollevel:Int?
87
+    
88
+    //学校状态1正常10删除
89
+    var  schoolstate:Int?
90
+    
91
+    //错误率%
92
+    var  errorrate:Double?
93
+    
94
+    //当前年份
95
+    var  year:Int?
96
+    
97
+    //性别1男2女
98
+    var  usersex:Int?
99
+    
100
+    //区域码
101
+    var  cloudcode:String?
102
+    
103
+    //班级id
104
+    var  classid:Int?
105
+    
106
+    //
107
+    var  xznum:Int?
108
+    
109
+    // token
110
+    var  token_value:String?
111
+    
112
+    
113
+    // 从NSObject解析回来
114
+    
115
+    required  init?(coder aDecoder:NSCoder){
116
+        self.userid=aDecoder.decodeObject(forKey: "userid") as? Int
117
+        self.username=aDecoder.decodeObject(forKey: "username") as? String
118
+        self.loginname=aDecoder.decodeObject(forKey: "loginname") as? String
119
+        self.loginpwd=aDecoder.decodeObject(forKey: "loginpwd") as? String
120
+        self.studentno=aDecoder.decodeObject(forKey: "studentno") as? String
121
+        self.userphone=aDecoder.decodeObject(forKey: "userphone") as? String
122
+        self.userbirthday=aDecoder.decodeObject(forKey: "userbirthday") as? Int
123
+        self.cardid=aDecoder.decodeObject(forKey: "cardid") as? String
124
+        self.headpic=aDecoder.decodeObject(forKey: "headpic") as? String
125
+        self.usertype=aDecoder.decodeObject(forKey: "usertype") as? Int
126
+        
127
+        self.userstate=aDecoder.decodeObject(forKey: "userstate") as? Int
128
+        self.bindmac=aDecoder.decodeObject(forKey: "bindmac") as? Int
129
+        self.mac=aDecoder.decodeObject(forKey: "mac") as? String
130
+        self.macname=aDecoder.decodeObject(forKey: "macname") as? String
131
+        self.sbindmac=aDecoder.decodeObject(forKey: "sbindmac") as? Int
132
+        self.opepassword=aDecoder.decodeObject(forKey: "opepassword") as? String
133
+        self.createid=aDecoder.decodeObject(forKey: "createid") as? Int
134
+        self.createname=aDecoder.decodeObject(forKey: "createname") as? String
135
+        self.createtime=aDecoder.decodeObject(forKey: "createtime") as? Int
136
+        self.deleteid=aDecoder.decodeObject(forKey: "deleteid") as? Int
137
+        self.deletetime=aDecoder.decodeObject(forKey: "deletetime") as? Int
138
+        self.schoolid=aDecoder.decodeObject(forKey: "schoolid") as? Int
139
+        self.schoolname=aDecoder.decodeObject(forKey: "schoolname") as? String
140
+        self.schoollevel=aDecoder.decodeObject(forKey: "schoollevel") as? Int
141
+        self.schoolstate=aDecoder.decodeObject(forKey: "schoolstate") as? Int
142
+        self.errorrate=aDecoder.decodeObject(forKey: "errorrate") as? Double
143
+        self.year=aDecoder.decodeObject(forKey: "year") as? Int
144
+        self.usersex=aDecoder.decodeObject(forKey: "usersex") as? Int
145
+        self.cloudcode=aDecoder.decodeObject(forKey: "cloudcode") as? String
146
+        self.classid=aDecoder.decodeObject(forKey: "classid") as? Int
147
+        self.xznum=aDecoder.decodeObject(forKey: "xznum") as? Int
148
+        self.token_value=aDecoder.decodeObject(forKey: "token_value") as? String
149
+        
150
+    }
151
+    
152
+    //编码成object,哪些属性需要归档,怎么归档
153
+    func encode(with aCoder: NSCoder) {
154
+        aCoder.encode(userid,forKey:"userid")
155
+        aCoder.encode(username,forKey:"username")
156
+        aCoder.encode(loginname,forKey:"loginname")
157
+        aCoder.encode(loginpwd,forKey:"loginpwd")
158
+        aCoder.encode(studentno,forKey:"studentno")
159
+        aCoder.encode(userphone,forKey:"userphone")
160
+        aCoder.encode(userbirthday,forKey:"userbirthday")
161
+        aCoder.encode(cardid,forKey:"cardid")
162
+        aCoder.encode(headpic,forKey:"headpic")
163
+        aCoder.encode(usertype,forKey:"usertype")
164
+        aCoder.encode(userstate,forKey:"userstate")
165
+        aCoder.encode(bindmac,forKey:"bindmac")
166
+        aCoder.encode(mac,forKey:"mac")
167
+        aCoder.encode(macname,forKey:"macname")
168
+        aCoder.encode(sbindmac,forKey:"sbindmac")
169
+        aCoder.encode(opepassword,forKey:"opepassword")
170
+        aCoder.encode(createid,forKey:"createid")
171
+        aCoder.encode(createname,forKey:"createname")
172
+        aCoder.encode(createtime,forKey:"createtime")
173
+        aCoder.encode(deleteid,forKey:"deleteid")
174
+        aCoder.encode(deletetime,forKey:"deletetime")
175
+        aCoder.encode(schoolid,forKey:"schoolid")
176
+        aCoder.encode(schoolname,forKey:"schoolname")
177
+        aCoder.encode(schoollevel,forKey:"schoollevel")
178
+        aCoder.encode(schoolstate,forKey:"schoolstate")
179
+        aCoder.encode(errorrate,forKey:"errorrate")
180
+        aCoder.encode(year,forKey:"year")
181
+        aCoder.encode(usersex,forKey:"usersex")
182
+        aCoder.encode(cloudcode,forKey:"cloudcode")
183
+        aCoder.encode(classid,forKey:"classid")
184
+        aCoder.encode(xznum,forKey:"xznum")
185
+        aCoder.encode(token_value,forKey:"token_value")
186
+        
187
+    }
188
+    
110 189
 }
111 190
 

+ 11
- 1
iOSFirst/login/LoginViewModel.swift View File

@@ -26,7 +26,17 @@ class LoginViewModel  {
26 26
             .request(AccountService.login(username, password, false)) {[weak self] json in
27 27
                 //            self?.mTextView.text = String(describing: JSON(json))
28 28
                 self?.userResponse.onNext(json)
29
-
29
+                let userDefault=UserDefaults.standard
30
+                userDefault.setValue(true, forKey: "isLogin")
31
+                let bool = userDefault.bool(forKey: "isLogin")
32
+                log.info(bool)
33
+                // 实例对象转化成NSData
34
+                let encodedObject = NSKeyedArchiver.archivedData(withRootObject: json)
35
+                // 储存NSData对象
36
+                userDefault.set(encodedObject, forKey: "userinfo")
37
+                let decodeObject = NSKeyedUnarchiver.unarchiveObject(with: userDefault.object(forKey: "userinfo") as! Data ) as! LoginUserInfo
38
+                print(decodeObject.token_value ?? "")
39
+                
30 40
             } failure: {code, msg in
31 41
                 log.info("code : \(code!)")
32 42
                 log.info("message : \(msg)")

+ 1
- 1
iOSFirst/network/API.swift View File

@@ -8,7 +8,7 @@
8 8
 import Foundation
9 9
 enum Api {
10 10
     /// baseUrl
11
-    static let shoolurl = "https://schoolapitest.xhkjedu.com/"
11
+    static let shoolurl = "https://schoolapi.xhkjedu.com/"
12 12
     
13 13
     static let fileurl = "https://schoolstatictest.xhkjedu.com/static/"
14 14
     

+ 71
- 2
iOSFirst/network/NetworkManager.swift View File

@@ -81,13 +81,78 @@ final class TdwMoyaPlugin: PluginType {
81 81
     }
82 82
 }
83 83
 
84
+/*
85
+ Moya默认有4个插件分别为:
86
+ AccessTokenPlugin 管理AccessToken的插件
87
+ CredentialsPlugin 管理认证的插件
88
+ NetworkActivityPlugin 管理网络状态的插件
89
+ NetworkLoggerPlugin 管理网络log的插件
90
+ */
91
+// 插件,实现pluginType可以实现在网络请求前转菊花,请求完成结束转菊花,或者写日志等功能
92
+struct NetworkPlugin: PluginType {
93
+    let userDefault=UserDefaults.standard
94
+
95
+    /// Called to modify a request before sending.(可进行数据加密等)
96
+    func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
97
+        var mRequest = request
98
+        let key = "XINGHUOLIAOYUAN7"
99
+        let jsonString = AESEncryptor.aes_encrypt(request.httpBody!.toHexString(),aes_key: key)
100
+//        mRequest.httpBody = jsonString.data(using: String.Encoding.utf8)
101
+        print("""
102
+                         #############↓网络请求参数↓#################
103
+                         \(target.baseURL)\(target.path)
104
+                         \(jsonString ?? "无参数")
105
+                         #############↑网络请求参数↑#################
106
+                         """)
107
+        let userinfo = NSKeyedUnarchiver.unarchiveObject(with: userDefault.object(forKey: "userinfo") as! Data ) as! LoginUserInfo
108
+        if(userDefault.bool(forKey: "isLogin")){
109
+            let bool = userDefault.bool(forKey: "isLogin")
110
+            log.info("prepare\(bool)")
111
+            let cc = userinfo.cloudcode == nil ? "" : userinfo.cloudcode  ?? ""
112
+            let id = userinfo.userid == nil ? "" : String(userinfo.userid ?? -1)
113
+            let tv = (userinfo.token_value == nil ? "" : userinfo.token_value) ?? ""
114
+            let key = "\(cc)_\(id)_p_phone_t"
115
+            mRequest.addValue(key, forHTTPHeaderField: "Token_Key")
116
+            mRequest.addValue(tv, forHTTPHeaderField: "Token_Value")
117
+        }
118
+        if let header = mRequest.allHTTPHeaderFields {
119
+            log.info("请求头内容\(header)")
120
+        }
121
+        return mRequest
122
+    }
123
+    
124
+    /// Called immediately before a request is sent over the network (or stubbed).(可进行网络等待,loading等)
125
+    func willSend(_ request: RequestType, target: TargetType) {
126
+//        guard let target = target as? AccountService else { return }
127
+//        let jsonData = try? JSONSerialization.data(withJSONObject: target.parameters, options: .prettyPrinted)
128
+//                let jsonString = String(data: jsonData ?? Data(), encoding: .utf8)
129
+//                print("""
130
+//                    #############↓网络请求参数↓#################
131
+//                    \(target.baseURL)\(target.path)
132
+//                    \(jsonString ?? "无参数")
133
+//                    #############↑网络请求参数↑#################
134
+//                    """)
135
+        
136
+    }
137
+
138
+    /// Called after a response has been received, but before the MoyaProvider has invoked its completion handler.(loading结束等)
139
+    func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
140
+    
141
+    }
142
+
143
+    /// Called to modify a result before completion.(可进行数据解密等)
144
+    func process(_ result: Result<Response, MoyaError>, target: TargetType) -> Result<Response, MoyaError> {
145
+        return result
146
+    }
147
+
148
+}
149
+
84 150
 
85 151
 
86 152
 let accountProvider = MoyaProvider<AccountService>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
87 153
 
88 154
 public class NetworkManaer{
89 155
     
90
-    
91 156
     /// 使用Moya的请求封装
92 157
     ///
93 158
     /// - Parameters:
@@ -95,11 +160,12 @@ public class NetworkManaer{
95 160
     ///   - success: 成功的回调
96 161
     ///   - error: 连接服务器成功但是数据获取失败
97 162
     ///   - failure: 连接服务器失败
163
+    ///
98 164
     public class func request<T: TargetType,U: HandyJSON>(_ target: T, success: @escaping((U) -> Void), failure: ((Int?, String) ->Void)?) {
99 165
         let provider = MoyaProvider<T>(
100 166
             endpointClosure: myEndpointClosure,
101 167
             requestClosure: requestClosure,
102
-            plugins: [networkPlugin],
168
+            plugins: [networkPlugin,NetworkPlugin.init()],
103 169
             trackInflights: false
104 170
             //            networkLoggerPlugin
105 171
         )
@@ -113,6 +179,7 @@ public class NetworkManaer{
113 179
                 do {
114 180
                     // *********** 这里可以统一处理错误码,弹出提示信息 ***********
115 181
                     let resObject = try? response.mapJSON()
182
+                    log.info("网络请求到的数据是:\(resObject)")
116 183
                     let responseObject = JSON(resObject ?? "")
117 184
                     let code = responseObject["code"].intValue
118 185
                     let msg = String(describing: responseObject["msg"])
@@ -124,6 +191,8 @@ public class NetworkManaer{
124 191
                         // 数据返回正确
125 192
                         success(responseData!)
126 193
                     case 2:
194
+                        let userDefault=UserDefaults.standard
195
+                        userDefault.setValue(false, forKey: "isLogin")
127 196
                         // 请重新登录
128 197
                         failure!(code,msg)
129 198
                         alertLogin(msg)

+ 43
- 16
iOSFirst/network/service/AccountService.swift View File

@@ -10,7 +10,7 @@ import Moya
10 10
 
11 11
 enum AccountService {
12 12
     case login(_ username: String, _ password: String, _ showLoading: Bool)
13
-   
13
+    
14 14
 }
15 15
 
16 16
 extension AccountService: TargetType {
@@ -35,27 +35,46 @@ extension AccountService: TargetType {
35 35
         }
36 36
     }
37 37
     
38
-//    var sampleData: Data {
39
-//        return Data()
40
-//    }
41
-//
38
+    //    var sampleData: Data {
39
+    //        return Data()
40
+    //    }
41
+    //
42 42
     var task: Task {
43 43
         switch self {
44 44
         case .login(let username, let password, _):
45
-        
46
-            return .requestParameters(parameters: ["loginname": username,
47
-                                                   "loginpwd": password,
48
-                                                   "ultype":"p_phone_t",
49
-                                                   "versionnum":"3.6.0"],
50
-                                      encoding: JSONEncoding.default)
45
+            return .requestParameters(parameters: parameters,
46
+                                      encoding: parameterEncoding)
47
+        default:
48
+            return .requestParameters(parameters: parameters, encoding: parameterEncoding)
51 49
         }
52 50
         
51
+        
52
+    }
53
+    
54
+    /// 参数
55
+    public var parameters: [String: Any] {
56
+        var parameters: [String: Any] = [:]
57
+        switch self {
58
+        case .login(let username, let password, _):
59
+            parameters = ["loginname": username, "loginpwd": password]
60
+        default:
61
+            break
62
+        }
63
+        for i in commParameters {
64
+            parameters[i.key] = i.value
65
+        }
66
+        return parameters
67
+    }
68
+    
69
+    /// 公共参数
70
+    public var commParameters: [String: Any?] {
71
+        ["ultype": "p_phone_t","versionnum":"3.7.1","logaddress": "","logip":""]
53 72
     }
54 73
     
55 74
     var headers: [String : String]? {
56 75
         switch self {
57 76
         case .login(_, _, let showLoading):
58
-            
77
+
59 78
             return [
60 79
                 "st":"false",
61 80
                 "Content-type":"application/json"]
@@ -66,11 +85,19 @@ extension AccountService: TargetType {
66 85
     }
67 86
     
68 87
     var sampleData: Data {
69
-            switch self {
70
-            case .login:
71
-                return "should be filled properly".utf8Encoded
72
-            }
88
+        switch self {
89
+        case .login:
90
+            return "should be filled properly".utf8Encoded
73 91
         }
92
+    }
93
+    
94
+    var parameterEncoding: ParameterEncoding {
95
+        switch self {
96
+        default:
97
+            //            return URLEncoding.default // application/x-www-form-urlencoded
98
+            return JSONEncoding.default // application/json; charset=utf-8
99
+        }
100
+    }
74 101
 }
75 102
 
76 103
 private extension String {

+ 64
- 0
iOSFirst/util/AES.swift View File

@@ -0,0 +1,64 @@
1
+//
2
+//  AES.swift
3
+//  iOSFirst
4
+//
5
+//  Created by 孙宇峰 on 2023/3/1.
6
+//
7
+
8
+import Foundation
9
+import CryptoSwift
10
+
11
+struct AESEncryptor {
12
+    
13
+
14
+    public  static func aes_encrypt(_ str:String, aes_key:String) -> String{
15
+     
16
+           var encryptedStr = ""
17
+           do {
18
+               //  AES encrypt
19
+               let encrypted = try AES(key: Array(aes_key.utf8), blockMode: ECB(), padding: .pkcs7).encrypt(str.bytes);
20
+//               let data = Data(base64Encoded: Data(encrypted), options: .ignoreUnknownCharacters)
21
+               //加密结果从data转成string 转换失败  返回""
22
+               encryptedStr = encrypted.toBase64()
23
+           } catch {
24
+               print(error.localizedDescription)
25
+           }
26
+           return encryptedStr
27
+       }
28
+
29
+    
30
+    /// AES-128-CBC 加密
31
+    /// - Parameter str: 加密字符串
32
+    public static func encode(to str: String) -> String? {
33
+        let key = "XINGHUOLIAOYUAN7"
34
+        guard let aes = try? AES(key: Array(key.utf8) ,blockMode: ECB(), padding:.pkcs5) else {
35
+            return nil
36
+        }
37
+        
38
+        guard let encrypted = try? aes.encrypt(str.bytes) else {
39
+            return nil
40
+        }
41
+        //
42
+        let encryptedBase64 = encrypted.toBase64()
43
+        return encryptedBase64
44
+    }
45
+    
46
+    
47
+    /// AES-128-CBC 解密
48
+    /// - Parameter str: 加密字符串
49
+    public static func decode(to str: String) -> String? {
50
+        let key = "XINGHUOLIAOYUAN7"
51
+        guard let aes = try? AES(key: Array(key.utf8), blockMode: ECB(), padding: .pkcs5) else {
52
+            return nil
53
+        }
54
+        guard let decrypted = try? str.decryptBase64ToString(cipher: aes) else {
55
+            return nil
56
+        }
57
+        return decrypted
58
+    }
59
+    
60
+    
61
+    
62
+    
63
+}
64
+

+ 26
- 0
iOSFirst/util/ShareProfsUtil.swift View File

@@ -0,0 +1,26 @@
1
+//
2
+//  ShareProfsUtil.swift
3
+//  iOSFirst
4
+//
5
+//  Created by 孙宇峰 on 2023/3/1.
6
+//
7
+
8
+import Foundation
9
+import HandyJSON
10
+
11
+
12
+extension UserDefaults{
13
+    func saveCustomObject(customObject object: NSData, key: String) { //2
14
+        let encodedObject = NSKeyedArchiver.archivedData(withRootObject: object)
15
+        self.set(encodedObject, forKey: key)
16
+        self.synchronize()
17
+    }
18
+    
19
+    func getCustomObject<T:HandyJSON>(forKey key: String) -> T? { //3
20
+        let decodedObject = self.object(forKey: key) as! Data
21
+        let object = NSKeyedUnarchiver.unarchiveObject(with: decodedObject )
22
+        return object  as? T
23
+    }
24
+}
25
+
26
+

Loading…
Cancel
Save