当我解析json时,它将所有内容都变为零

时间:2017-09-24 18:01:35

标签: objective-c swift swift4 xcode9

当我用swift调用我的php文件并检索json时,它返回字节

http://jacobwebb.xyz/app.php - 我用来显示数据的链接

现在我认为当我得到它时一切都很好,因为它在输出中返回可选(275字节)但是当我尝试解析数据然后再次打印时,所有内容都会变回零,如下所示,我会看到2个不同的json对象并尝试运行它然后返回nil。

抱歉如果这可能很简单,我正在学习如何在swift中编码。

姓名:nil,地址:nil,纬度:nil,经度:nil,id:nil,信息:nil,time:nil

姓名:nil,地址:nil,纬度:nil,经度:nil,id:nil,信息:nil,time:nil

这是我的viewController.swift

//
//  ViewController.swift
//  dropDeals
//
//  Created by jacob webb on 9/23/17.
//  Copyright © 2017 jacob webb. All rights reserved.
//

import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
    @IBOutlet weak var map: MKMapView!
    let manager = CLLocationManager()
    var locTimer = Timer()
    var found = false
    var data = Data()
    let urlPath: String = "http://jacobwebb.xyz/app.php"

    override func viewDidLoad() {
        super.viewDidLoad()

        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
        //Start event
        locTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.getJsonFromUrl), userInfo: nil, repeats: true)

        self.getJsonFromUrl()
    }
    @objc func getJsonFromUrl(){

        let url: URL = URL(string: urlPath)!
        let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)

        let task = defaultSession.dataTask(with: url) { (data, response, error) in

            if error != nil {
                print("Failed to download data")
            }else {
                print("Data downloaded")
                print(data)
                self.parseJSON(data!)
            }

        }

        task.resume()
    }

    func parseJSON(_ data:Data) {

        var jsonResult = NSArray()

        do{
            jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray

        } catch let error as NSError {
            print(error)

        }

        var jsonElement = NSDictionary()
        let locations = NSMutableArray()

        for i in 0 ..< jsonResult.count
        {

            jsonElement = jsonResult[i] as! NSDictionary

            let location = LocationModel()

            //the following insures none of the JsonElement values are nil through optional binding
            if let name = jsonElement["Name"] as? String,
                let address = jsonElement["Address"] as? String,
                let latitude = jsonElement["Latitude"] as? String,
                let longitude = jsonElement["Longitude"] as? String,
                let id = jsonElement["id"] as? Int,
                let info = jsonElement["info"] as? String,
                let time = jsonElement["time"] as? Int {
                location.name = name
                location.address = address
                location.latitude = latitude
                location.longitude = longitude
                location.id = id
                location.info = info
                location.time = time
            }

            locations.add(location)
            print(location)
        }

        DispatchQueue.main.async(execute: { () -> Void in

        })
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if found == false {
            let location = locations[0]
            let span:MKCoordinateSpan = MKCoordinateSpanMake(0.04, 0.04)
            let coord:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
            let currentRegion:MKCoordinateRegion = MKCoordinateRegionMake(coord, span)
            map.setRegion(currentRegion, animated: true)
            self.map.showsUserLocation = true
            found = true
        }
    }
}

这是我的LocationModel对象

//
//  LocationModel.swift
//  dropDeals
//
//  Created by jacob webb on 9/24/17.
//  Copyright © 2017 jacob webb. All rights reserved.
//

import Foundation

class LocationModel: NSObject {

    //properties

    var name: String?
    var address: String?
    var latitude: String?
    var longitude: String?
    var id: Int?
    var info: String?
    var time: Int?

    //empty constructor

    override init()
    {

    }

    //construct with @name, @address, @latitude, and @longitude parameters

    init(name: String, address: String, latitude: String, longitude: String, id: Int, info: String, time: Int) {

        self.name = name
        self.address = address
        self.latitude = latitude
        self.longitude = longitude
        self.id = id
        self.info = info
        self.time = time
    }


    //prints object's current state

    override var description: String {
        return "Name: \(name), Address: \(address), Latitude: \(latitude), Longitude: \(longitude), id: \(id), Info: \(info), time: \(time)"

    }


}

1 个答案:

答案 0 :(得分:2)

你的逻辑是有缺陷的。用简单的if let替换您的大let逗号列表:

let name = jsonElement["Name"] as? String
let address = jsonElement["Address"] as? String
let latitude = jsonElement["Latitude"] as? String
let longitude = jsonElement["Longitude"] as? String
let id = jsonElement["id"] as? Int
let info = jsonElement["info"] as? String
let time = jsonElement["time"] as? Int
location.name = name
location.address = address
location.latitude = latitude
location.longitude = longitude
location.id = id
location.info = info
location.time = time

那不是你想要的。

其中一些 nil,因为你说的是​​nil,它总是失败; JSON字典中的所有内容都是String。如果你想制作一个Int,你必须强制到Int;你不能简单地施放到一个Int并且这样做。例如,您可能会说:

nil

同样适用于as? Int

但是,我强烈建议你学习Swift 4,这种事情基本上是微不足道的。你设计的模型很差,所以需要做一些额外的准备工作:

let id : Int? = {
    if let id = jsonElement["id"] as? String {
        return Int(id)
    } else {
        return nil
    }
}()
然而,在那之后,它真的很简单。这是测试字符串:

time

现在,真正神奇的部分:

struct LocationModel : Decodable {
    var name: String?
    var address: String?
    var latitude: String?
    var longitude: String?
    var id: Int?
    var info: String?
    var time: Int?
    enum Keys : String, CodingKey {
        case name = "Name"
        case address = "Address"
        case latitude = "Latitude"
        case longitude = "Longitude"
        case id
        case info
        case time
    }
    init(from decoder: Decoder) throws {
        let con = try decoder.container(keyedBy: Keys.self)
        self.name = try con.decode(String.self, forKey: .name)
        self.address = try con.decode(String.self, forKey: .address)
        self.latitude = try con.decode(String.self, forKey: .latitude)
        self.longitude = try con.decode(String.self, forKey: .longitude)
        self.id = Int(try con.decode(String.self, forKey: .id))
        self.info = try con.decode(String.self, forKey: .info)
        self.time = Int(try con.decode(String.self, forKey: .time))
    }
}

这就是全部!