Swift下Data处理全流程:从网络下载,数模转换,本地缓存到页面使用

Swift下将网络返回json数据转换成struct
假如网络请求返回的数据结构是一个深层嵌套的Json
首先要通过key-value取出这个json中的数据源
// 将返回的json字符串转Dictory let json = """ {     "name": "jack",     "age": 20,     "description": "A student." } """.data(using: .utf8)! if let jsonData = jsonString.data(using: .utf8) {     do {         let json = try JSONSerialization.jsonObject(with: jsonData, options: [])         if let dictionary = json as? [String: Any],            let key2 = dictionary["key2"] as? [String: Any],            let innerKey2 = key2["key2"] as? [String: Any],            let value = innerKey2["key1"] as? String {             print(value) // 输出"value3"         }     } catch {         print("解析JSON数据失败:(error)")     } }

数模转换
// 定义数据类型,遵守Codable协议 // 注意定义的类型与接口返回对应,否则JSONSerialization时崩溃 // Struct模型可以根据json中的数据关系对应嵌套 struct ContactSimpleModel: Codable {     var relation: String     var name: String      struct ContactSimpleModel1: Codable {     var relation: String     var name: String          struct ContactSimpleModel2: Codable {         var relation: String         var name: String         }      } }

 

字典与struct互相转换

将字典转换成struct模型
根据网络返回的Dictory,从里面取出数组widgets: Array<[String: Any]>
1.map遍历数组,拿到每一个数组元素字典
2.处理每个元素,先使用JSONSerialization.data(withJSONObject:将字典转成data,
3.再使用JSONDecoder().decode(ContactSimpleModel.self, from: data)将data转成struct结构体。
4.使用struct模型
let decoder = JSONDecoder() let resList = try widgets.map { (item) -> AdJsonModel in     let data = try JSONSerialization.data(withJSONObject: item, options: [])     let res = try decoder.decode(AdJsonModel.self, from: data)     return res } return resList

struct模型转字典
也可以通过给Encodable协议加默认实现,提供便捷Struct转字典方法
// 扩展 Encodable 协议 extension Encodable {     var dictionary: [String: Any]? {         if let data = try? JSONEncoder().encode(self) {             if let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {                 return dict             }             return nil         }         return nil     }  }

 
Struct本地缓存
假如没有使用数据库,通过UserDefaults或者Plist文件保存。
使用data进行保存到UserDefaults
struct Person: Codable {     var name: String     var age: Int }  var people = [Person(name: "John", age: 30), Person(name: "Mary", age: 25)] //转成data保存 let data = try! JSONEncoder().encode(people) UserDefaults.standard.set(data, forKey: "peopleData") //取 if let data = UserDefaults.standard.data(forKey: "peopleData") {     let people = try! JSONDecoder().decode([Person].self, from: data) }

使用Dictionary保存到Plist文件
本地文件处理
路径判断,创建目录用Url.path
创建目录案例
    lazy var adListDirPath: String? = {         let documentDic = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first         let adUrl = documentDic?.appendingPathComponent(":ad")         if let adUrlSub = adUrl {             var isDic: ObjCBool = ObjCBool(false)             // 判断adUrlSub.path路径是否存在,如果是文件路径则isDic=false, 如果是目录路径isDic=true             if FileManager.default.fileExists(atPath: adUrlSub.path, isDirectory: &isDic) && isDic.boolValue {                 return adUrlSub.absoluteString             }                          do {                 // 如果路径不存在,则创建本地路径,withIntermediateDirectories: true表示如果路径中间有未创建的,则把中间的目录也创建                 try FileManager.default.createDirectory(at: adUrlSub, withIntermediateDirectories: true, attributes: nil)                 return adUrlSub.absoluteString             } catch {                 Logger.error(":adDataManager", content: error.localizedDescription)                 return nil             }         }         return nil     }()

写文件要用Url.absoluteString
swift中保存plist文件,使用NSDictionary进行保存

1.先删除历史文件  do {     try FileManager.default.removeItem(at: filePathUrl)     return true } catch {     Logger.error(":adDataManager", content: error.localizedDescription)     return false } 2.保存新文件 NSDictionary(object: adList, forKey: adListRootKey).write(to: filePathUrl, atomically: true) 3.读取本地文件 let dict = try NSDictionary(contentsOf: filePathUrl, error: ())

zip文件解压
  func unzipFile() {     let zipPath = "/path/to/zip/file"     let destinationPath = "/path/to/destination/folder"     do {         try ZipArchive.unzipFile(atPath: zipPath, toDestination: destinationPath)     } catch {         print("Error unzipping file: (error.localizedDescription)")     } } 

 

先缓存后使用,提高用户体验
SDWebImage的先预下载图片,等启动时直接使用缓存的方法
//0.自定义设置缓存大小 URLCache.shared = URLCache(memoryCapacity: 10 * 1024 * 1024, diskCapacity: 50 * 1024 * 1024, diskPath: nil) //1.缓存 SDWebImage批量下载图片 SDWebImagePrefetcher.shared().prefetchURLs方法下载的图片本地路径默认是Library/Caches/com.hackemist.SDWebImageCache.default目录下的缓存文件。 可以通过SDWebImageManager.shared().imageCache.diskCachePath方法获取具体路径。 //2.使用 在UIImageView加载图片时,使用AAImageView.sd_setImage(with: url, placeholderImage: nil)进行价值 

 

注意:
对于可选类型的数组,如果没有拆包就map, 那么闭包的入参是拆包的数组
let list = dict[adListRootKey] as? Array<[String: Any]> if let listSub = list {     let decoder = JSONDecoder()     let resList = listSub.map { (item) -> AdJsonModel? in 

 

 

 

 

 

发表评论

评论已关闭。

相关文章