在 Swift 中动态存储和访问数据的最佳方式

Posted

技术标签:

【中文标题】在 Swift 中动态存储和访问数据的最佳方式【英文标题】:Best way to dynamically store and access data in Swift 【发布时间】:2020-09-29 09:07:37 【问题描述】:

我有一个应用程序,每次启动时(在初始屏幕内),它都会通过 API 端点从我的数据库中获取当前登录的用户数据。 当应用请求数据时,预期返回给应用的 JSON 类型如下所示:


"username": "test",
"email": "test@gmail.com",
"uid": "5f661ffe1a80160027a6cb0c",
"isVerified": true,
"hub": 
    "hubID": "npnDsZegiSL5",
    "isSetup": true,
    "hubSWVersion": 0.11,
    "_id": "5f661ffe1a80160027a6cb0d",
    "cameraService": 
        "isSetup": true,
        "bridgeIP": "192.168.0.12",
        "username": "JesCGSr6HrWoKbKnnNOHSayVKdb1"
    ,
    "servicesSetup": 
        "1": "cameraService",
        "2": "TPLinkPlug"
    
,
    "code": "100",
    "message": "Success. User details have been provided"

随着用户添加服务/更新值,此数据库结构将不断变化。这是我的问题。有很多这样的问题都有相同的答案,使用 JSONDecoder 并将值推送到可观察对象,该对象可以通过创建它的实例在整个应用程序中访问,或者只是简单地将值分配给获取对象时的对象。我已经完成并且目前正在使用的:

userData对象:

class userData: NSObject, ObservableObject 
    var userdata = userData.self
    @Published var uid: String = ""
    @Published var isVerified: Bool = false
    @Published var username: String = ""
    @Published var email: String = ""

当我在我的应用程序中收到上述 json 时,我将值分配给对象的代码:

...
@EnvironmentObject var user: userData
print("Successfully got user data. Code: \(code ?? "0"). UID: \(response?["uid"] as! String). Username: \(response?["username"] as! String)")
DispatchQueue.main.async 
user.email = response?["email"] as! String
user.uid = response?["uid"] as! String
user.username = response?["username"] as! String
...

然后我可以通过我的任何地方访问它:

@EnvironmentObject var user: userData
username = self.user.username

但这需要硬编码代码来分配我的数据库中的每个值,是否有更好、更动态的方法来将来自我的 API 的整个 json 响应(无论有什么值/嵌入的 json)分配给一个对象并通过该对象在我的应用中访问这些数据值?

谢谢

【问题讨论】:

您可以将响应存储为 Dictionary 并遍历键而不是硬编码字段。 @MohammadRahchamani 如果您认为这是最好的方法,您能否在此评论中添加示例代码作为答案,以便此问题可以帮助包括我在内的其他人? @MohammadRahchamani 我如何能够从应用程序内的任何位置访问所述字典? 这取决于您的架构。例如,您可以将该字典作为EnvironmentObject 传递。或将其存储在您的数据库等中。 【参考方案1】:

因为您的响应中将包含新的键值对,所以我认为您应该将响应存储为 Dictionary 并从该字典中获取所需的值,而不是解析响应并存储单独的变量。 这是一个例子:

    let jsonStr = """
        \"username\": \"test\",
        \"email\": \"test@gmail.com\",
        \"uid\": \"5f661ffe1a80160027a6cb0c\",
        \"isVerified\": true,
        \"hub\": 
            \"hubID\": \"npnDsZegiSL5\",
            \"isSetup\": true,
            \"hubSWVersion\": 0.11,
            \"_id\": \"5f661ffe1a80160027a6cb0d\",
            \"cameraService\": 
                \"isSetup\": true,
                \"bridgeIP\": \"192.168.0.12\",
                \"username\": \"JesCGSr6HrWoKbKnnNOHSayVKdb1\"
            ,
            \"servicesSetup\": 
                \"1\": \"cameraService\",
                \"2\": \"TPLinkPlug\"
            
        ,
            \"code\": \"100\",
            \"message\": \"Success. User details have been provided\"
        
    """
    
    let data = jsonStr.data(using: .utf8)
    
    do 
        // store this variable
        let dict =  try JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any]
        
        for (k,v) in dict! 
            // example access to values
            print("key: \(k), value: \(v)")
        
        
     catch 
        print(error.localizedDescription)
    

【讨论】:

您正在使用jsonStr 传递给JSONSerialization 函数。我有一个从我的 API 返回的 json 对象。如果我改为传递那个 json 对象(try JSONSerialization.jsonObject(with: json!, options: []) 我得到错误:Type of expression is ambiguous without more context 我要么需要让 json 对象返回与上面相同的格式,要么使用不同的函数? 我假设您收到的回复为String 它有效,我之前已经这样做了,只是我无法获得嵌入到该 json 中的值,例如hub中的值 因为hub 值本身就是Dictionary,您应该将其转换为Dictionary 以访问其中的值。例如:让 hubDict = dict["hub"] as!字典

以上是关于在 Swift 中动态存储和访问数据的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

在关系数据库中存储(和访问)历史 1:M 关系的最佳方式是啥?

在数据库中存储动态字段时的最佳实践

Swift 核心数据更改 bool 存储

在应用程序中存储静态数据的最佳方式

从应用程序中存储的文本文件中读取数据的最佳方式

存储数据(表)的最佳方式并易于访问以表示它