если пусть не может присвоить значение переменной - PullRequest
0 голосов
/ 15 мая 2018

Я занимаюсь разработкой приложения, которое может извлекать данные из fitbitapi и отображать их в виде таблицы, однако при попытке добавить данные, полученные из веб-API, к исходной модели, вот мой код

for json in jsons.values {
        print("json is \(json)")
        if let Json = json as? [String : Any]{

            var healthData : StepStats? = nil
            if let date = Json["dateTime"] as? String,
                let value = Json["value"] as? Int{
                healthData = StepStats(dateTime : date, value : value as AnyObject)

            }
            if let HealthData = healthData {
                model.append(HealthData)
            }

        }
        else {
            print("Unexpected Error")

        }

Каждый раз, когда я запускаю этот код, он выдает неожиданную ошибку, и Json = nil, здесь находится начальный json

    {
    dateTime = "2018-04-15";
    value = 0;
},
    {
    dateTime = "2018-04-16";
    value = 6969;
},
}

Я думаю, что это формат данных Json, которые я получил, не отформатирован, иличто-то не так с моим кодом?Пожалуйста, помогите мне, я новичок в Swift, так что это может быть основной ошибкой, но любая помощь будет признательна.

Непарсированные данные похожи на это

Optional("{\"activities-steps\":[{\"dateTime\":\"2018-04-17\",\"value\":\"7170\"},{\"dateTime\":\"2018-04-18\",\"value\":\"6443\"},{\"dateTime\":\"2018-04-19\",\"value\":\"11254\"},{\"dateTime\":\"2018-04-20\",\"value\":\"5771\"},{\"dateTime\":\"2018-04-21\",\"value\":\"33\"},{\"dateTime\":\"2018-04-22\",\"value\":\"2697\"},{\"dateTime\":\"2018-04-23\",\"value\":\"11\"},{\"dateTime\":\"2018-04-24\",\"value\":\"8\"},{\"dateTime\":\"2018-04-25\",\"value\":\"0\"},{\"dateTime\":\"2018-04-26\",\"value\":\"0\"},{\"dateTime\":\"2018-04-27\",\"value\":\"0\"},{\"dateTime\":\"2018-04-28\",\"value\":\"389\"},{\"dateTime\":\"2018-04-29\",\"value\":\"4916\"},{\"dateTime\":\"2018-04-30\",\"value\":\"0\"},{\"dateTime\":\"2018-05-01\",\"value\":\"0\"},{\"dateTime\":\"2018-05-02\",\"value\":\"0\"},{\"dateTime\":\"2018-05-03\",\"value\":\"0\"},{\"dateTime\":\"2018-05-04\",\"value\":\"1929\"},{\"dateTime\":\"2018-05-05\",\"value\":\"0\"},{\"dateTime\":\"2018-05-06\",\"value\":\"0\"},{\"dateTime\":\"2018-05-07\",\"value\":\"0\"},{\"dateTime\":\"2018-05-08\",\"value\":\"2818\"},{\"dateTime\":\"2018-05-09\",\"value\":\"6990\"},{\"dateTime\":\"2018-05-10\",\"value\":\"6558\"},{\"dateTime\":\"2018-05-11\",\"value\":\"15434\"},{\"dateTime\":\"2018-05-12\",\"value\":\"0\"},{\"dateTime\":\"2018-05-13\",\"value\":\"0\"},{\"dateTime\":\"2018-05-14\",\"value\":\"0\"},{\"dateTime\":\"2018-05-15\",\"value\":\"0\"},{\"dateTime\":\"2018-05-16\",\"value\":\"0\"},{\"dateTime\":\"2018-05-17\",\"value\":\"0\"}]}")

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Я добавлю еще один ответ, даже если StackOverflow посоветует мне отредактировать предыдущий ответ, но я не могу не заметить, что добавление ваших «новых» неразобранных данных в основном превращает этот вопрос в совершенно другой. Обычно вам следует задать другой вопрос и, возможно, оставить комментарий, который вы хотели бы продолжить в другом вопросе. Достаточно мета, теперь для ответа.

Хотя ваши «неразобранные данные» технически верны, они по-прежнему очень неудобны в двух отношениях. Линеаризованные необязательные параметры в конечном итоге будут экранированы, поэтому все ваши двойные кавычки будут экранированы (и в правильном JSON их будет множество), и не будет новых строк, которые трудно прочитать в StackOverflow, где вы должны постараться сохранить свои строки не слишком намного больше ширины типичного окна браузера. Об избежавших двойных кавычках можно позаботиться, просто развернув необязательные (с !), но добавить красивые новые строки немного сложнее. Однако, поскольку ваш JSON теперь в основном верен, я могу использовать его, чтобы показать некоторые другие тонкости протокола Codable. Если вы запустите эту игровую площадку:

import Cocoa

let string = "{\"activities-steps\":[{\"dateTime\":\"2018-04-17\",\"value\":\"7170\"},{\"dateTime\":\"2018-04-18\",\"value\":\"6443\"},{\"dateTime\":\"2018-04-19\",\"value\":\"11254\"},{\"dateTime\":\"2018-04-20\",\"value\":\"5771\"},{\"dateTime\":\"2018-04-21\",\"value\":\"33\"},{\"dateTime\":\"2018-04-22\",\"value\":\"2697\"},{\"dateTime\":\"2018-04-23\",\"value\":\"11\"},{\"dateTime\":\"2018-04-24\",\"value\":\"8\"},{\"dateTime\":\"2018-04-25\",\"value\":\"0\"},{\"dateTime\":\"2018-04-26\",\"value\":\"0\"},{\"dateTime\":\"2018-04-27\",\"value\":\"0\"},{\"dateTime\":\"2018-04-28\",\"value\":\"389\"},{\"dateTime\":\"2018-04-29\",\"value\":\"4916\"},{\"dateTime\":\"2018-04-30\",\"value\":\"0\"},{\"dateTime\":\"2018-05-01\",\"value\":\"0\"},{\"dateTime\":\"2018-05-02\",\"value\":\"0\"},{\"dateTime\":\"2018-05-03\",\"value\":\"0\"},{\"dateTime\":\"2018-05-04\",\"value\":\"1929\"},{\"dateTime\":\"2018-05-05\",\"value\":\"0\"},{\"dateTime\":\"2018-05-06\",\"value\":\"0\"},{\"dateTime\":\"2018-05-07\",\"value\":\"0\"},{\"dateTime\":\"2018-05-08\",\"value\":\"2818\"},{\"dateTime\":\"2018-05-09\",\"value\":\"6990\"},{\"dateTime\":\"2018-05-10\",\"value\":\"6558\"},{\"dateTime\":\"2018-05-11\",\"value\":\"15434\"},{\"dateTime\":\"2018-05-12\",\"value\":\"0\"},{\"dateTime\":\"2018-05-13\",\"value\":\"0\"},{\"dateTime\":\"2018-05-14\",\"value\":\"0\"},{\"dateTime\":\"2018-05-15\",\"value\":\"0\"},{\"dateTime\":\"2018-05-16\",\"value\":\"0\"},{\"dateTime\":\"2018-05-17\",\"value\":\"0\"}]}"

let jsonData = string.data(using: .utf8)!

struct Step: Codable {
    let value: String
    let dateTime : Date
}

struct Activity: Codable {
    let steps: [Step]
    enum CodingKeys: String, CodingKey {
        case steps = "activities-steps"
    }
}

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

do {
    let activity = try decoder.decode(Activity.self, from: jsonData)

    let encoder = JSONEncoder()
    encoder.dateEncodingStrategy = .formatted(formatter)
    encoder.outputFormatting = .prettyPrinted
    let data = try encoder.encode(activity)
    print(String(data: data, encoding: .utf8)!)
} catch {
    print(error)
}

Это напечатает следующий довольно напечатанный JSON:

{
    "activities-steps" : [
        {
            "value" : "7170",
            "dateTime" : "2018-04-17"
        },
        {
            "value" : "6443",
            "dateTime" : "2018-04-18"
        },
        {
            "value" : "11254",
            "dateTime" : "2018-04-19"
        },
        {
            "value" : "5771",
            "dateTime" : "2018-04-20"
        },
        {
            "value" : "33",
            "dateTime" : "2018-04-21"
        },
        {
            "value" : "2697",
            "dateTime" : "2018-04-22"
        },
        {
            "value" : "11",
            "dateTime" : "2018-04-23"
        },
        {
            "value" : "8",
            "dateTime" : "2018-04-24"
        },
        {
            "value" : "0",
            "dateTime" : "2018-04-25"
        },
        {
            "value" : "0",
            "dateTime" : "2018-04-26"
        },
        {
            "value" : "0",
            "dateTime" : "2018-04-27"
        },
        {
            "value" : "389",
            "dateTime" : "2018-04-28"
        },
        {
            "value" : "4916",
            "dateTime" : "2018-04-29"
        },
        {
            "value" : "0",
            "dateTime" : "2018-04-30"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-01"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-02"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-03"
        },
        {
            "value" : "1929",
            "dateTime" : "2018-05-04"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-05"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-06"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-07"
        },
        {
            "value" : "2818",
            "dateTime" : "2018-05-08"
        },
        {
            "value" : "6990",
            "dateTime" : "2018-05-09"
        },
        {
            "value" : "6558",
            "dateTime" : "2018-05-10"
        },
        {
            "value" : "15434",
            "dateTime" : "2018-05-11"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-12"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-13"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-14"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-15"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-16"
        },
        {
            "value" : "0",
            "dateTime" : "2018-05-17"
        }
    ]
}

Теперь это по-прежнему громоздко как вопрос StackOverflow (обычно вам, вероятно, следует уменьшить его, так как это просто скучное повторение, но это нормально для первого вопроса), но в этой форме все еще намного легче переварить. И, надеюсь, он научил вас, как создавать Codable структуры для представления ваших данных в действительно Swifty форме и как отформатировать какой-то грязный JSON в более читаемый формат, который легче усваивается вашими глазами.

Очевидно, что JSON был прав, поскольку JSONDecoder удалось его проанализировать, но вам, как человеку, гораздо проще судить, как он должен выглядеть, когда вы видите его в довольно печатной форме.

Таким образом, ваш activity должен быть прост в обработке и использовать его в TableView, поэтому я надеюсь, что по крайней мере некоторые ваши проблемы были решены этим.

0 голосов
/ 15 мая 2018

Ваша распечатка выглядит почти как JSON, но это не так.Я предполагаю, что вы распечатываете объект, полученный из непродуманного JSONSerialization, который сам решит, что он анализирует из строки.Это можно контролировать намного проще и гораздо более универсально, применяя протокол Codable.Учитывая, что вы можете запустить следующую игровую площадку

import Cocoa

let jsonData = """
[
    {
        "dateTime":"2018-04-15",
        "value":0
    },
    {
        "dateTime":"2018-04-16",
        "value":6969
    }
]
""".data(using: .utf8)!

struct HealthData: Codable {
    let date: Date
    let value: Int

    private enum CodingKeys: String, CodingKey {
        case date = "dateTime"
        case value
    }
}

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

do {
    let datas = try decoder.decode([HealthData].self, from: jsonData)
    print(datas)
} catch {
    print(error)
}

, которая значительно упрощает вашу стратегию синтаксического анализа, так как большую часть ее выполняет JSONDecoder, для которой вы даже можете указать форматер даты.Пожалуйста, не стесняйтесь добавлять свой фактический JSON, если мое предположение было неверным, но, пожалуйста, опубликуйте содержимое String, полученного от вашего сервиса, вместо какой-то наполовину проанализированной структуры.

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