Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
229 views
in Technique[技术] by (71.8m points)

ios - JSON parsing swift, array has no value outside NSURLSession

I am trying to call a json webservice in swift, With the following code and display it in tableview in swift IOS.

/*declared as global*/ var IdDEc = [String]() // string array declared globally

//inside viewdidload

let url = NSURL(string: "http://192.1.2.3/PhpProject1/getFullJson.php")

let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in

let json1 = NSString(data: data!, encoding: NSUTF8StringEncoding)

print("json string is = ",json1) // i am getting response here

let data = json1!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)

? ? do {

? ? ? ? let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSArray

? ? ? ? ? ? for arrayData in json {

? ? ? ? ? ? ? ? let notId = arrayData["ID"] as! String

? ? ? ? ? ? ? ? self.IdDEc.append(notId)
? ? ? ? ? ? }

? ? ? ? ? ? print(" id = ",IdDEc) //here i am getting values

? ? ? ? } catch let error as NSError {

? ? ? ? ? ? print("Failed to load: (error.localizedDescription)")
? ? ? ? }

? ? ? ? print(" id? out count = ",self.IdDEc.count) //here also
? ? }

? ? print(" id? out count = ",self.IdDEc.count) // not here

? ? task.resume()

i declared the array IdDEc as global, still the scope of that array resides inside NSURLSession only,

Also i want to use this array to populate tableview. Here is the sample json output file

[

{"ID":"123"?,?"USER":"philip","AGE":"23"},

{"ID":"344","USER":"taylor","AGE":"29"},

{"ID":"5464","USER":"baker","AGE":"45"},

{"ID":"456","USER":"Catherine","AGE":"34"}

]

I am a newbee in swift please help

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The idea is to use a "callback".

Here, I've made one for the NSArray you want to get:

completion: (dataArray: NSArray)->()

We create a function to get the array, and we add this callback to the function's signature:

func getDataArray(urlString: String, completion: (dataArray: NSArray)->())

and as soon as the array is ready we'll use the callback:

completion(dataArray: theNSArray)

Here's how the complete function could look like:

func getDataArray(urlString: String, completion: (dataArray: NSArray)->()) {
    if let url = NSURL(string: urlString) {
        NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
            if error == nil {
                if let data = data,
                    json1 = NSString(data: data, encoding: NSUTF8StringEncoding),
                    data1 = json1.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
                    do {
                        let json = try NSJSONSerialization.JSONObjectWithData(data1, options: [])
                        if let jsonArray = json as? NSArray {
                            completion(dataArray: jsonArray)
                        }
                    } catch let error as NSError {
                        print(error.localizedDescription)
                    }
                } else {
                    print("Error: no data")
                }
            } else {
                print(error!.localizedDescription)
            }
        }.resume()
    }
}

Now we use this function like this, no more asynchronous issues:

getDataArray("http://192.1.2.3/PhpProject1/getFullJson.php") { (dataArray) in
    for dataDictionary in dataArray {
        if let notId = dataDictionary["ID"] as? String {
            self.IdDEc.append(notId)
        }
    }
    print("id out count = ", self.IdDEc.count)
}

Swift 3 update + fixes and improvements.

func getContent(from url: String, completion: @escaping ([[String: Any]])->()) {
    if let url = URL(string: url) {
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            if error == nil  {
                if let data = data {
                    do {
                        let json = try JSONSerialization.jsonObject(with: data, options: [])
                        if let content = json as? [[String: Any]] { // array of dictionaries
                            completion(content)
                        }
                    } catch {
                        // error while decoding JSON
                        print(error.localizedDescription)
                    }
                } else {
                    print("Error: no data")
                }
            } else {
                // network-related error
                print(error!.localizedDescription)
            }
        }.resume()
    }
}

getContent(from: "http://192.1.2.3/PhpProject1/getFullJson.php") { (result) in
    // 'result' is what was given to 'completion', an array of dictionaries
    for dataDictionary in result {
        if let notId = dataDictionary["ID"] as? String {
            // ...
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...