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

网络,页面,流程,数模 · 浏览次数 : 184

小编点评

```swift struct AdJsonModel: Codable { var relation: String var name: String } // 解析 JSON 数据 let jsonData = jsonString.data(using: .utf8) if let json = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] { let key2 = json["key2"] as? [String: Any] let innerKey2 = key2["key2"] as? [String: Any] let value = innerKey2["key1"] as? String print(value) } ``` **解释:** 1. **Struct Model** 定义了一个名为 `AdJsonModel` 的结构体,包含 `relation` 和 `name` 属性。 2. **JSON 解析** 读取 JSON 数据并将其解析为 `[String: Any]` 类型。 3. **提取值** 从 `json` 中提取 `key2` 和 `key2` 的子元素,并从子元素中获取 `key1` 属性的值。 4. **将值打印** ,并打印出来。 **注意:** * `jsonString` 是一个 JSON 字符串。 * `AdJsonModel` 结构体要与 JSON 数据结构一致。 * 如果 JSON 数据是嵌套的,则需要使用 `map` 或其他方法处理它。

正文

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)进行价值 
//3.删除缓存
SDWebImageManager.shared.imageCache.removeImage(forKey: $0, cacheType: SDImageCacheType.all)

 

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

 

 

 

 

 

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

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

Swift下将网络返回json数据转换成struct 假如网络请求返回的数据结构是一个深层嵌套的Json 首先要通过key-value取出这个json中的数据源 // 将返回的json字符串转Dictory let json = """ { "name": "jack", "age": 20, "d

最近常用的几个【行操作】的Pandas函数

theme: smartblue 最近在做交易数据的统计分析时,多次用到数据行之间的一些操作,对于其中的细节,简单做了个笔记。 1. shfit函数 shift函数在策略回测代码中经常出现,计算交易信号,持仓信号以及资金曲线时都有涉及。这个函数的主要作用是将某列的值上下移动。默认情况下,shift函

windows离线部署VSCode在Centos7上的远程开发环境

前言 公司一直使用的是ssh+vim的远程开发方式,习惯了vim之后已经非常方便了。但是还是想尝试一下VSCode的开发方式。就我而言,原因如下 漂亮的语法高亮,并且有补全 基于语法解析的引用查找(尽管在我们项目的场景下还是一坨翔) Ctrl+Shift+F的快速搜索 可视化调试,可以直接在代码中下

Swift开发基础08-高阶函数

高阶函数是指接受其它函数作为参数,或者返回其它函数的函数。Swift 提供了许多内置的高阶函数,这些函数在处理集合类型数据(如数组、集合等)时尤其有用。常见的高阶函数包括 map、filter、reduce、flatMap 和 compactMap。 一、常用高阶函数 1. map map 函数会对

Swift开发基础06-闭包

Swift的闭包(Closures)是一种将功能块和上下文整合并演示在代码中的一种手段。闭包可以捕获并存储其上下文中的变量和常量。与普遍存在于其他语言的匿名函数(如Python的lambda、JavaScript的函数表达式)类似,Swift的闭包提供了强大的功能,并在很多场景中替代了函数。 闭包有

深入理解 Swift Combine

Combine 文中写一些 Swift 方法签名时,会带上 label,如 subscribe(_ subscriber:),正常作为 Selector 的写法时会忽略掉 label,只写作 subscribe(_:) ,本文特意带上 label 以使含义更清晰。 Combine Framework

Swift中发布-订阅框架Combine的使用

Combine简介 Combine是一个苹果用来处理事件的新的响应式框架,支持iOS 13及以上版本。 你可以使用Combine去统一和简化在处理类似于target-action,delegate,kvo等事情的代码。 iOS目前已经有第三方的响应式框架了,如:RxSwift、ReactiveCoc

Swift中UITableViewDiffableDataSource的使用

在 iOS 13 中 Apple 为 UITableView 和 UICollectionView 引入了 DiffableDataSource, 让开发者可以更简单高效的实现 UITableView、UICollectionView 的局部数据刷新。 新的刷新的方法为 apply 通过使用 app

Swift之struct二进制大小分析

随着Swift的日渐成熟和给开发过程带来的便利性及安全性,京喜App中的原生业务模块和基础模块使用Swift开发占比逐渐增高。本次讨论的是struct对比Class的一些优劣势,重点分析对包体积带来的影响及规避措施。

Swift与OC混编

Swift调OC 在Swift项目中调用OC类中的方法需要有个{targetName}-Bridging-Header.h文件,在这个文件中导入OC要暴露给Swift的类。 {targetName}-Bridging-Header.h文件的创建有2种方式 1.自己手动创建,然后在配置文件的Objec