简体   繁体   中英

Returning Data from JSON Parse - Swift

So I'm a newbie with Swift, and somewhat with programming in general. I've only been doing it since the first of the year... I'm trying to make a simple app that pulls data from an external JSON file, and inputs it into UILabels. I've gotten the data to pull, and append to an array. From here, it seems to exit the scope and not be useable anywhere else... I've created a struct that is to hold the data, accordingly. As you can see, I've added print markers to see what is going on, visually.

  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)
    }

I know I'm missing something really simple...but I'm at a loss... Any help/info is appreciated!

There are a few issues with this code:

First: The JSON you are receiving is not in the format your code expects. The root object isn't a dictionary but an array.

if let JSONfile = json as? [String: Any] {

changes to

if let JSONfile = json as? [[String: String]] {

This also requires you to loop over each item.

print("JSON Reading")
for item in JSONfile {

As the dictionary definition has changed from [String:Any] to [String:String] the as? String as? String statements are no longer needed either.

Second: I'm not sure if you realise this or not (maybe you already do) but the bits of code after the //Loses Scope line run first . Before the Companies AGIAN AGAIN and Companies AGIAN AGAIN AGAIN lines.

They might be further down the page but the lines above that are in a closure that runs after the file has downloaded and so execute later after the other lines have already run.


Here is the complete fixed code (formatted in such a way you can copy and paste it into an Xcode Playground to see it working).

// 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()

And you will get this output, which helps explain what is going on (though I removed the actual company names).

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"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM