#swift
#swift
Вопрос:
У меня есть следующий код:
//create an NSURL
let url = NSURL(string: self.urlString)
//fetch the data from the url
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
//If the retrieved information is a JSON Object, and can be treated as an NSArray...
if let jsonObj = (try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSObject) {
let data = jsonObj.value(forKey: "pendingloads") as! NSArray
for item in data {
if let itemObject = item as? NSObject {
print("Tons value1: (itemObject.value(forKey: "tons")!)")
let tons = itemObject.value(forKey: "tons") as? Double ?? nil
print("Tons value2: (String(describing: tons))")
Я делаю это, потому что у меня есть возможность получить null из этих данных. Моя проблема в том, что я всегда получаю двойное значение (когда элемент возвращает единицу) при первой печати, но ноль во второй. Это потому, что значение itemObject.value (forKey: «тонны») является необязательным?
Я попытался принудительно развернуть значение, но затем оно прерывается, когда оно равно нулю. Мне нужно, чтобы он был обнуляемым, но у меня возникли проблемы с выполнением этого всеми документированными способами. Я знаю, что на этот вопрос есть очень простой ответ, но я просто еще не нашел его. Любая помощь была бы очень признательна.
Соответствующий JSON:
}
"pendingloads": [
{
"comment": "Test Comment",
"hauler": "Test Hauler",
"logs": [
{
"coords": "(25.123456, -120.123456)",
"type": "auth",
"timestamp": "2019-04-04 10:52:1554393131",
"device_id": "DEVICE-ID-DEVICE-ID-DEVICEID"
},
{
"coords": "(25.123456, -120.123456)",
"type": "update",
"timestamp": "2019-04-08 13:38:1554748736",
"device_id": "DEVICE-ID-DEVICE-ID-DEVICEID"
}
],
"tons": "12.800",
"load_id": 23,
"requires_correction": false,
"trailer_drop": true,
"gross": "25600.000",
"contract_id": 3679,
"scaleticket": "2134098",
"destination": "TEST DESTINATION",
"sale_id": 3961,
"tare": "0.000",
"net": "25600.000",
"cull": "157.000",
"product": "Test Product",
"operator_id": 2674,
"hauler_id": 617,
"timestamp": "2019-04-08 18:38:1554766680",
"driver": "Terry",
"ticket": 250,
"product_id": 3172,
"sale": "Test Sale",
"trailer": "013724589"
}
]
}
В надежде на улучшение, вот обновленный код:
//create a URL
let url = URL(string: self.urlString)
//fetch the data from the url
URLSession.shared.dataTask(with: (url)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = (try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as AnyObject) {
let data = jsonObj.value(forKey: "pendingloads") as! Array<AnyObject>
for item in data {
let itemObject = item as AnyObject
Комментарии:
1.
?? nil
является избыточным. И вы злоупотребляетеString(describing
. И вам не рекомендуется использоватьvalue(forKey
, если вы действительно не знаете и не нуждаетесь в KVC.2. Если первая
nil
тогда значение для keytons
явно не являетсяDouble
3. Тогда логически значение равно
String
4. OMG:
as? NSObject) as NSObject??
это ужасно. Не могли бы вы, пожалуйста, добавить соответствующую часть JSON.5. Весь код ужасает. Вы пишете нереконструированный Objective-C так, как если бы это был Swift. Вы не должны использовать NSObject, JSONSerialization, NSURL или
value(forKey:)
.
Ответ №1:
Вы можете попробовать
struct Root: Codable {
let pendingloads: [Pendingload]
}
struct Pendingload: Codable {
let comment, hauler: String
let logs: [Log]
let tons: String
let loadId: Int
let requiresCorrection, trailerDrop: Bool
let gross: String
let contractId: Int
let scaleticket, destination: String
let saleId: Int
let tare, net, cull, product: String
let operatorId, haulerId: Int
let timestamp, driver: String
let ticket, productId: Int
let sale, trailer: String
}
struct Log: Codable {
let coords, type, timestamp, deviceId: String
}
let url = URL(string: self.urlString)!
URLSession.shared.dataTask(with:url) { (data, response, error) in
guard let data = data else { return }
do {
let res = JSONDecoder()
res.keyDecodingStrategy = .convertFromSnakeCase
let ss = try res.decode(Root.self, from:data)
print(ss)
}
catch {
print(error)
}
}.resume()