当我用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)"
}
}
答案 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))
}
}
这就是全部!