从JSON解析返回数据 - 斯威夫特
问题描述:
所以我和斯威夫特一个新手,并稍微与一般的编程。我只是一直在做这件事,因为第一年的......我试图做一个简单的应用程序,从外部JSON文件中提取数据,并将其输入到UILabels。我得到的数据拉,并追加到一个数组。从这里,它似乎退出了范围,不能在其他地方使用......我创建了一个结构来保存数据。正如你所看到的,我已经添加了打印标记来直观地看到发生了什么。从JSON解析返回数据 - 斯威夫特
struct GlobalTestimonialData {
var testimonialsText: [String]
var customerNames: [String]
var companyNames: [String]
}
var TestimonialData = GlobalTestimonialData(testimonialsText: [""], customerNames: [""], companyNames: [""])
func getData() {
let requestURL: URL = URL(string: "https://szadydesigns.com/test/mobileapp/testimonials.php")!
let urlRequest = URLRequest(url: requestURL as URL)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("File has been downloaded!")
do {
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments)
print("JSON Serialized")
if let JSONfile = json as? [String: AnyObject] {
print("JSON Reading")
if let testimonial = JSONfile["testimonial"] as? [String] {
print("Testimonials Read")
TestimonialData.testimonialsText.append(contentsOf: testimonial)
print(TestimonialData.testimonialsText)
print("Inside of loop Testimonial Text Number: \(TestimonialData.testimonialsText.count)")
if let name = JSONfile["name"] as? [String] {
print("Names Read")
TestimonialData.customerNames.append(contentsOf: name)
print(TestimonialData.customerNames)
print("Inside of loop Customers Number: \(TestimonialData.customerNames.count)")
}
if let company = JSONfile["company"] as? [String] {
print("Companies Read")
TestimonialData.companyNames.append(contentsOf: company)
print(TestimonialData.companyNames)
}
print("Companies: \(TestimonialData.companyNames)")
}
print("COMPANIES: \(TestimonialData.companyNames)")
}
print("Companies AGIAN: \(TestimonialData.companyNames)")
}catch {
print("Error with Json: \(error)")
}
print("Companies AGIAN AGAIN : \(TestimonialData.companyNames)")
}
print("Companies AGIAN AGAIN AGAIN: \(TestimonialData.companyNames)")
}
//Loses Scope
print("Companies AGIAN TIMES : \(TestimonialData.companyNames)")
task.resume()
print("Outside of loop Customers Number: \(TestimonialData.customerNames.count)")
print("Outside of loop Testimonial Text Number: \(TestimonialData.testimonialsText.count)")
print(TestimonialData.companyNames)
}
我知道我错过了一些非常简单的事情......但我无所适从...任何帮助/信息都会感激!
答
没有与此代码的几个问题:
第一:您收到的JSON是不是在你的代码期望的格式。根对象不是字典而是数组。
if let JSONfile = json as? [String: Any] {
变化
if let JSONfile = json as? [[String: String]] {
这也需要你遍历每个项目。
print("JSON Reading")
for item in JSONfile {
正如字典中的定义已经从[String:Any]
到[String:String]
的as? String
语句改变是不再被需要。
二:我不知道你是否意识到这一点(也许你已经这样做了),但//Loses Scope
线运行第一后的码位。在Companies AGIAN AGAIN
和Companies AGIAN AGAIN AGAIN
之前。
他们可能进一步下来的页面,但上面说是在运行该文件下载等以后执行后,其他线路已经运行后封闭线。
下面是完整的固定码(以这样的方式,你可以将它复制并粘贴到一个Xcode游乐场看到它的工作格式)。
// Xcode 8.2, Swift 3
import Cocoa
import PlaygroundSupport
// Required for the download to work.
PlaygroundPage.current.needsIndefiniteExecution = true
struct GlobalTestimonialData {
var testimonialsText: [String]
var customerNames: [String]
var companyNames: [String]
}
var testimonialData = GlobalTestimonialData(testimonialsText: [], customerNames: [], companyNames: [])
func getData() {
let requestURL: NSURL = NSURL(string: "https://szadydesigns.com/test/mobileapp/testimonials.php")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: requestURL as URL)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) { (data, response, error) in
let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
print("File has been downloaded!")
do {
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments)
print("JSON Serialized")
if let JSONfile = json as? [[String: String]] {
print("JSON Reading")
for item in JSONfile {
if let testimonial = item["testimonial"] {
testimonialData.testimonialsText.append(testimonial)
if let name = item["name"] {
testimonialData.customerNames.append(name)
}
if let company = item["company"] {
testimonialData.companyNames.append(company)
}
}
}
}
} catch {
print("Error with Json: \(error)")
}
}
print("Companies Last: \(testimonialData.companyNames)")
print(" ")
print(testimonialData)
}
//Loses Scope
print("Companies 1 : \(testimonialData.companyNames)")
task.resume()
print("Before the download of the JSON Customer names count: \(testimonialData.customerNames.count)")
print("Before the download of the JSON Testimonial Text Number: \(testimonialData.testimonialsText.count)")
print(testimonialData.companyNames)
}
getData()
你会得到这个输出,这有助于解释发生了什么(虽然我删除了实际的公司名称)。
Companies 1 : []
Before the download of the JSON Customer names count: 0
Before the download of the JSON Testimonial Text Number: 0
[]
File has been downloaded!
JSON Serialized
JSON Reading
Companies: ["REMOVED_1", "REMOVED_2", "REMOVED_3", "REMOVED_4"]
您使用的是故事板?你的代码不在任何你想链接到故事板的自定义类中,所以我很困惑你将如何显示数据。 – Bawpotter
你缺少调用回调,task.resume后'打印线()'总会打印*没有数据*'因为工作dataTask'异步。在你的代码中还有另一个大的设计错误:一个自定义结构应该为每个**证明创建一个**实例,而不是保存多个数组。在Swift 3中,为JSON字典使用原生的'URL','URLRequest'和'[String:Any]'。 – vadian
是的,我正在使用故事板。上面的代码是它自己的.Swift文件,以保持ViewController'干净'。 – szady