如何访问可选 NSSingleObjectArrayI 中的值?

Posted

技术标签:

【中文标题】如何访问可选 NSSingleObjectArrayI 中的值?【英文标题】:How can I access values within Optional NSSingleObjectArrayI? 【发布时间】:2019-04-04 18:16:44 【问题描述】:

我不知道如何访问从 JSON 响应构造的嵌套可选 NSSingleObjectArrayI 中的“持续时间”值。如何访问此数据结构中的嵌套值?

当我调用 print(firstRow["elements"]) 时,我得到以下输出:

Optional(<__NSSingleObjectArrayI 0x60000120f920>(

    distance = 
        text = "1.8 km";
        value = 1754;
    ;
    duration = 
        text = "5 mins";
        value = 271;
    ;
    "duration_in_traffic" = 
        text = "4 mins";
        value = 254;
    ;
    status = OK;

))

我尝试了字符串索引 (firstRow['elements']['duration']),但出现错误。

fetchData  (dict, error) in
    if let rows = dict?["rows"] as? [[String:Any]]
        if let firstRow = rows[0] as? [String:Any]
            print("firstRow is")
            print(firstRow["elements"])
            // Trying to access duration within firstRow['elements'] here           
        
    

作为参考,这是 fetchData 函数:

func fetchData(completion: @escaping ([String:Any]?, Error?) -> Void) 

    let url = getRequestURL(origin: "test", destination: "test")!;

    let task = URLSession.shared.dataTask(with: url)  (data, response, error) in
        guard let data = data else  return 
        do 
            if let array = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any]
                completion(array, nil)
            
         catch 
            print(error)
            completion(nil, error)
        
    
    task.resume()

这里有一个示例 HTTP JSON 请求:

https://maps.googleapis.com/maps/api/distancematrix/json?destinations=77%20Massachusetts%20Ave,%20Cambridge,%20MA&departure_time=now&key=AIzaSyB65D4XHv6PkqvWJ7C-cFvT1QHi9OkqGCE&origins=428%20Memorial%20Dr,%20Cambridge,%20MA

【问题讨论】:

请问可以添加原始json并解析代码吗?因此,帮助您会容易得多。 你也可以先尝试解开你的数组吗?例如像这样:firstRow['elements'][0]['duration'] 或 firstRow['elements'].first['duration'] 使用 Codable,而不是 JSONSerialization。 @matt 你能详细说明一下吗?我对 Codable 不是很熟悉。 @AntonVlasov 我试过了,结果为零:( 【参考方案1】:

看到你的输出,你的firstRow["elements"] 是可选的,所以你需要解开它。它实际上是一个带有单个元素的 NSArray,其中唯一的元素是一个 Dictionary,有 4 个条目——“distance”、“duration”、“duration_in_traffic”和“status”。您可能需要将元素转换为 Dictionary 以访问每个条目。

您可以为此目的使用带有as?-casting 的可选绑定:

fetchData  (dict, error) in
    if let rows = dict?["rows"] as? [[String: Any]] 
        if let firstRow = rows.first 
            print("firstRow is")
            print(firstRow["elements"])
            //Unwrap and cast `firstRow["elements"]`.
            if let elements = firstRow["elements"] as? [[String: Any]] 
                //The value for "duration" is a Dictionary, you need to cast it again.
                if let duration = elements.first?["duration"] as? [String: Any] 
                    print(duration["text"] as? String)
                    print(duration["value"] as? Int)
                
            
        
    

或者嵌套太深的ifs 难以阅读,所以有人会喜欢它:

fetchData  (dict, error) in
    if
        let rows = dict?["rows"] as? [[String: Any]],
        let firstRow = rows.first,
        let elements = firstRow["elements"] as? [[String: Any]],
        let duration = elements.first?["duration"] as? [String: Any]
    
        print(duration["text"] as? String)
        print(duration["value"] as? Int)
    

或者使用guard 可能是更好的解决方案。


或者,如果您可以以可读格式向我们展示整个 JSON 文本,那么有人会向您展示如何使用 Codable,这是在 Swift 中使用 JSON 的一种现代方式。

【讨论】:

谢谢!我通过swiftjson.com 很容易地实现了 Codeable 并获得了我的 Codeable 类 @Willy,您似乎找到了一个可以与Codable 合作的漂亮网站。编码愉快。

以上是关于如何访问可选 NSSingleObjectArrayI 中的值?的主要内容,如果未能解决你的问题,请参考以下文章

访问无价值的隐式解包可选?

访问编译错误:参数不是可选的

您将如何使用 Spring Boot 处理仅具有可选查询参数的 REST API?

如何在 react-router v4 的根路由上设置可选参数?

Nest.js 中使用 @nestjs/passport 的可选身份验证

访问修饰符与可选修饰符static的使用