Swift - 解析 JSON 并检索数据
Swift - Parsing JSON and retrieve data
我在 Xcode 上与 Swift 合作,我尝试解析 JSON 文件以检索有关附近商店的一些数据。
我的源代码如下:
import GooglePlaces
import SwiftyJSON
class Place {
let name: String
let coordinates: CLLocationCoordinate2D
init(diction:[String : Any])
{
let json = JSON(diction)
name = json["name"].stringValue //as! String
let lat = json["geometry"]["location"]["lat"].doubleValue as CLLocationDegrees
let long = json["geometry"]["location"]["lng"].doubleValue as CLLocationDegrees
coordinates = CLLocationCoordinate2DMake(lat, long)
}
}
class ViewController: UIViewController, MKMapViewDelegate, SceneLocationViewDelegate {
var urlString = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?"
urlString += "&location=51.507514,-0.073603"
urlString += "&radius=1500" //meters
urlString += "&name=Specsavers"
urlString += "&key=**************************"
guard let url = URL(string: urlString) else {return}
var places = [Place]()
var request = URLRequest(url:url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
print("HEREurlSession")
if let content = data {
do {
let json = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(json) // json results are printed fine here
if let results = json["results"] as? [[String : Any]] {
for place in results {
places.append(Place(diction: place))
}
}
else {
print("return")
}
}
catch{
}
}
}
task.resume()
let size = places.count
print("HERE: ", size)
}
构建成功但输出为size = 0
,这意味着我没有检索数据并且变量places
为空。
我不知道它是否完全相关,但我收到以下警告:Cast from 'MDLMaterialProperty?!' to unrelated type '[[String : Any]]' always fails
for the line if let results = json["results"] as? [[String : Any]]
in my source code.
为什么我没有正确解析 JSON 文件并且没有检索到我想要的数据?
URLSession.shared.dataTask(with:)
是异步的。这意味着,它在后台运行。您正在执行
let size = places.count
print("HERE: ", size)
而 dataTask
仍在工作。
相反,您应该在完成处理程序中使用您的结果:
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
print("HEREurlSession")
if let content = data {
do {
let json = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(json)
if let results = json["results"] as? [[String : Any]] {
for place in results {
places.append(Place(diction: place))
}
}
else {
print("return")
}
}
catch{
}
}
// Use your result here
let size = places.count
useResultSize(size)
}
task.resume()
func useResultSize(_ size: Int) {
// Use your result here
print("HERE: ", size)
}
更新
看来,您忽略了异步执行的真正含义。让我试着解释一下。
让我们在代码中标记执行顺序:
首先,执行代码的红色部分。程序执行从顶部开始,然后移动到底部的红色框,只有在那之后(一旦网络请求完成)绿色部分才被执行。
也就是说,你只能使用代码绿色部分的网络请求结果。绿色部分以外,不保证结果可用
如果您遵循我最初的建议,那么一切都应该可行。请在我的操场上查看成功执行:
我在 Xcode 上与 Swift 合作,我尝试解析 JSON 文件以检索有关附近商店的一些数据。 我的源代码如下:
import GooglePlaces
import SwiftyJSON
class Place {
let name: String
let coordinates: CLLocationCoordinate2D
init(diction:[String : Any])
{
let json = JSON(diction)
name = json["name"].stringValue //as! String
let lat = json["geometry"]["location"]["lat"].doubleValue as CLLocationDegrees
let long = json["geometry"]["location"]["lng"].doubleValue as CLLocationDegrees
coordinates = CLLocationCoordinate2DMake(lat, long)
}
}
class ViewController: UIViewController, MKMapViewDelegate, SceneLocationViewDelegate {
var urlString = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?"
urlString += "&location=51.507514,-0.073603"
urlString += "&radius=1500" //meters
urlString += "&name=Specsavers"
urlString += "&key=**************************"
guard let url = URL(string: urlString) else {return}
var places = [Place]()
var request = URLRequest(url:url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
print("HEREurlSession")
if let content = data {
do {
let json = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(json) // json results are printed fine here
if let results = json["results"] as? [[String : Any]] {
for place in results {
places.append(Place(diction: place))
}
}
else {
print("return")
}
}
catch{
}
}
}
task.resume()
let size = places.count
print("HERE: ", size)
}
构建成功但输出为size = 0
,这意味着我没有检索数据并且变量places
为空。
我不知道它是否完全相关,但我收到以下警告:Cast from 'MDLMaterialProperty?!' to unrelated type '[[String : Any]]' always fails
for the line if let results = json["results"] as? [[String : Any]]
in my source code.
为什么我没有正确解析 JSON 文件并且没有检索到我想要的数据?
URLSession.shared.dataTask(with:)
是异步的。这意味着,它在后台运行。您正在执行
let size = places.count
print("HERE: ", size)
而 dataTask
仍在工作。
相反,您应该在完成处理程序中使用您的结果:
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
print("HEREurlSession")
if let content = data {
do {
let json = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(json)
if let results = json["results"] as? [[String : Any]] {
for place in results {
places.append(Place(diction: place))
}
}
else {
print("return")
}
}
catch{
}
}
// Use your result here
let size = places.count
useResultSize(size)
}
task.resume()
func useResultSize(_ size: Int) {
// Use your result here
print("HERE: ", size)
}
更新
看来,您忽略了异步执行的真正含义。让我试着解释一下。
让我们在代码中标记执行顺序:
首先,执行代码的红色部分。程序执行从顶部开始,然后移动到底部的红色框,只有在那之后(一旦网络请求完成)绿色部分才被执行。
也就是说,你只能使用代码绿色部分的网络请求结果。绿色部分以外,不保证结果可用
如果您遵循我最初的建议,那么一切都应该可行。请在我的操场上查看成功执行: