Как я могу получить доступ к значениям в дополнительном NSSingleObjectArrayI? - PullRequest
0 голосов
/ 04 апреля 2019

Я не знаю, как получить доступ к значению «длительности» в моем вложенном дополнительном NSSingleObjectArrayI, который создан из ответа JSON.Как получить доступ к вложенным значениям в этой структуре данных?

Когда я вызываю 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;
}
))

Я пробовал строкуindexing (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

1 Ответ

0 голосов
/ 05 апреля 2019

Видя ваш вывод, ваш firstRow["elements"] является опциональным, поэтому вам нужно развернуть его. И это на самом деле NSArray с одним элементом, где единственным элементом является словарь, с 4 записями - «расстояние», «продолжительность», «duration_in_traffic» и «статус». Возможно, вам придется привести элемент в словарь, чтобы получить доступ к каждой записи.

Для этой цели вы можете использовать опциональную привязку с as? -кастингом:

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)
                }
            }
        }
    }
}

Или слишком глубоко вложенные if трудно читать, поэтому кто-то хотел бы это как:

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, который является современным способом работы с JSON в Swift.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...