Create variables from JSON array - ios

I'm trying hard to learn IOS development.
I have followed this guide and successfully managed to create a working quiz game. The last couple of days I have been trying to connect the game to an external database. Finally after many hours I'm able to read from MYSQL using JSON parsing.
Right now Im struggling with a way to convert the json array into a normal array.
My current hardcoded questions look like this:
let questionOne = questionTemplate("the first question?", answerOne: "a answer", answerTwo: "a second answer", answerThree: "a third aswer", answerFour: "tast possible answer", correctAnswer: 2)
Then they are added to an array
spormslaArray = [questionOne, questionTwo, questionThree, questionFour, questionFive, questionSix,questionSeven]
Then im doing some more loading of answers and questions before i add them to the GUI based on an array counter from the first to the last question.
func questionTemplate(question:String, answerOne:String, answerTwo:String, answerThree:String, answerFour:String, correctAnswer:Int) -> NSArray {
//Set the question
var quizQuestion = question
//set the answers and the right answer
var firstAnswer = answerOne
var secondAnswer = answerTwo
var thirdAnswer = answerThree
var fourthAnswer = answerFour
var rightAnswer = correctAnswer
var gjennverendeSporsmal = 1
//Add all the questions and answers to an array
let questionAnswerArray = [question, firstAnswer, secondAnswer, thirdAnswer, fourthAnswer, rightAnswer]
return questionAnswerArray
}
I now want to add questions from my database into spormslaArray.I got questions loaded into xcode using this code:
func lasteJson(){
let urlPath = "http://universellutvikling.no/utvikling/json.php"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
if error != nil {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if err != nil {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
let json = JSON(jsonResult)
let count: Int? = json["data"].array?.count
// println("found \(count!) challenges")
//Im just setting a hardcoded number, it will be based on the array when I have figured that out
var tall = 7
let ct = count
for index in 0...tall-1 {
println(json["data"][index] )
//DEtte printer ut induviduelt
/*
if let questionId = json["data"][index]["id"].string {
println(questionId)
}
if let spm1 = json["data"][index]["answerOne"].string {
println(spm1)
}
if let spm2 = json["data"][index]["answerTwo"].string {
println(spm2)
}
if let spm3 = json["data"][index]["answerThree"].string {
println(spm3)
}
if let spm4 = json["data"][index]["answerFour"].string {
println(spm4)
}
if let correctAnswer = json["data"][index]["correctAnswer"].string {
println(correctAnswer)
}
*/
}
//}
})
task.resume()
This is mostly based on this code.
If Im ignoring the fact that Im getting some breakpoints when im running the app, and that nordic characters in my database makes the ios simulator crash; This is the parsing result in the command line:
{
"correctAnswer" : "1",
"id" : "0",
"answerThree" : "aa3",
"answerFour" : "aa4",
"questionTemplate" : "sporsmal",
"answerOne" : "as1",
"answerTwo" : "aa2"
}
//////Finally here is the problem///////
I have tried for hours to make a variable from the json array, into the guestion array.
I want to do something like this:
let questionOne = json["data"][index]["answerOne"].string
and then add them to an array
let questionArray[questionOne, QuestionTwo.. etc]
I have tried for hours without any progress, so my last hope is you guys! :-)

Use this...
To post JSON or to receive JSON (Leave dictionary nil to GET)
///Use completion handler to handle recieved data
func sendJSON(params:Dictionary<String, String>?, toAdressOnServer:String, customCompletionHandler:((parsedData:AnyObject?, statusCode: Int) -> Void)?){
var request = NSMutableURLRequest(URL: NSURL(string: SERVER_NAME + toAdressOnServer)!)
var session = NSURLSession.sharedSession()
var err: NSError?
if (params == nil){
request.HTTPMethod = "GET"
}else{
request.HTTPMethod = "POST"
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params!, options: nil, error: &err)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments , error: &err)
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
customCompletionHandler?(parsedData: json, statusCode: -1)
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON: AnyObject = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
// Use keyword "success" in JSON from server to register successful transmission
let success = parseJSON["success"] as? Int
if (success == nil){
customCompletionHandler?(parsedData: json, statusCode: -2)
}else{
customCompletionHandler?(parsedData: json, statusCode: success!)
}
}
else {
// The json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
customCompletionHandler?(parsedData: json, statusCode: -1)
}
}
})
task.resume()
}
And To decode the JSON in your case the array, but it can have any form.
self.sendJSON(nil, toAdressOnServer: "ADRESS", customCompletionHandler: { (parsedData, statusCode) -> Void in
//check for valid data
if (parsedData != nil){
//Loop through results
for (var x = 0; x < parsedData!.count; x++){
///primary key of the item from the internet
let pk:Int = (parsedData![x] as NSDictionary).objectForKey("pk") as Int
let month = ((parsedData![x] as NSDictionary).objectForKey("fields") as NSDictionary).objectForKey("month")! as String
let quote = ((parsedData![x] as NSDictionary).objectForKey("fields") as NSDictionary).objectForKey("quote")! as String
let quotee = ((parsedData![x] as NSDictionary).objectForKey("fields") as NSDictionary).objectForKey("quotee")! as String
})
This is an example, use parsed data as "json" and use it with the appropriate structure. In this case the JSON was An array of some dictionary with a fields dictionary that has another dictionary with more fields. So you can have any JSON structure.
I Hope this helps!

It seems that you almost have the answer there. I think what you are missing is questionArray.append(... in your loop to build your array. You could also make things easier for yourself if you modified your JSON so that the questions were in an array rather than discrete keys and change your questionTemplate to take an array rather than discrete answers.
Working with what you have however -
func lasteJson(){
let urlPath = "http://universellutvikling.no/utvikling/json.php"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
questionsArray=[Question]()
let task = session.dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in
if error != nil {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
else {
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if err != nil {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
else {
let questions=jsonResult["data"] as? [[String:String]]
if (questions != nil) {
for question in questions! {
let answer1=question["answerOne"]!
let answer2=question["answerTwo"]!
let answer3=question["answerThree"]!
let answer4=question["answerFour"]!
let id=question["id"]!
let questionTemplate=question["questionTemplate"]!
let correctAnswer=question["correctAnswer"]!
let newQuestion=Question(questionTemplate, answerOne: answer1, answerTwo:answer2, answerThree: answer3, answerFour: answer4, correctAnswer: correctAnswer)
questionsArray.append(newQuestion)
}
}
}
}
})
task.resume()
}
You don't show your questionTemplate, but I am not sure why/how it returns an array. My code above assumes that there is a class Question and fills in a property questionsArray

Related

Xcode - Swift 2.0: "Extra argument 'error' in call" with NSJSONSerialization [duplicate]

This question already has an answer here:
iOS: JSONObjectWithData
(1 answer)
Closed 5 years ago.
I'm working on an app that features a login screen, which is a first for me. After following different websites that provided tutorials for this, I made a LoginService ViewController that would help with the process of signing in to the app.
Here is a part of the code that I've used in this ViewController:
// MARK: Private Methods
private func exchangeTokenForUserAccessTokenWithCompletionHandler(username: String, password: String, completion: (OAuthInfo?, error: String?) -> ()) {
let path = "/oauthfake/token/"
let url = ConnectionSettings.apiURLWithPathComponents(path)
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
var params = "client_id=\(ConnectionSettings.clientId)&client_secret=\(ConnectionSettings.clientSecret)&grant_type=password&login=\(username)&password=\(password)"
var err: NSError?
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let task = session.dataTaskWithRequest(request) {data, response, error -> Void in
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
if (err != nil) {
// Something went wrong, log the error to the console.
print(err!.localizedDescription)
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Something went wrong: '\(jsonStr)")
completion(nil, error: err?.localizedDescription)
} else {
if let parseJSON = json {
if let token = parseJSON.valueForKey("access_token") as? String {
if var issuedAt = parseJSON.valueForKey("issued_at") as? String {
if var tokenExpiresIn = parseJSON.valueForKey("expires_in") as? String {
if var refreshTokenIssuedAt = parseJSON.valueForKey("refresh_token_issued_at") as? String {
if let refreshToken = parseJSON.valueForKey("refresh_token") as? String {
if var refreshTokenExpiresIn = parseJSON.valueForKey("refresh_token_expires_in") as? String {
if let refreshCount = parseJSON.valueForKey("refresh_count") as? String {
let epochIssuedAt:Double = (issuedAt as NSString).doubleValue / 1000.0
let epochRefreshTokenIssuedAt:Double = (refreshTokenIssuedAt as NSString).doubleValue / 1000.0
let oauthInfo = OAuthInfo(issuedAt: epochIssuedAt, refreshTokenIssuedAt: epochRefreshTokenIssuedAt, tokenExpiresIn: (tokenExpiresIn as NSString).doubleValue, refreshToken: refreshToken, token: token, refreshTokenExpiresIn: (refreshTokenExpiresIn as NSString).doubleValue, refreshCount: (refreshCount as NSString).integerValue)
completion(oauthInfo, error: err?.localizedDescription)
My super.init seems to work fine (not featured above), as well as the rest of the code in this file, but I get one error reading "Extra argument 'error' in call" on this line:
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
I have already gathered that Swift 2.0 handles errors differently to what I'm used to. I know that this version of Swift uses try, let and catch codes for errors. My issue is I haven't used any of these types of code before and am unsure on how to use them in this particular situation.
On iOS 7 and latter NSJSONSerialization is thread safe.Now you can use it using do try catch
Swift 3:
do{
let JsonDict = try JSONSerialization.jsonObject(with: data, options:.MutableLeaves)
}
catch let error as NSError {
print(error)
}
Swift 2:
do{
let jsonDict = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves) as! [String:AnyObject]
}catch let error as NSError{
print(error)
}
The JSONObjectWithData function requires the do try catch syntax you mentioned because the method at its declaration site is marked with the throws keyword. (Documentation here: https://developer.apple.com/reference/foundation/jsonserialization/1418059-jsonobject)
No to use it simply.
do {
try someMethodWhichCanThrow()
catch(error) {
// maybe log the error here
}
This is described in the Swift Programming language book here: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID508

Parse JSON response with SwiftyJSON without crash

My iOS app is getting JSON response from server
let myURL = NSURL(string: SERVER_URL);
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = ""
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
if error != nil {
print("error=\(error)")
return
}
dispatch_async(dispatch_get_main_queue(),{
var json = JSON(data: data!)
let someInt = json["someInt"].int
let message = json["message"].stringValue
Sometimes server is down or there may be errors in JSON so there will be no such values (message, someInt) and I want to handle it without app crash - what can I do?
With SwiftyJSON, non-optional getters end with Value, and optional getters don't.
So to test if the value is here you can use optional binding with if let:
if let someInt = json["someInt"].int,
message = json["message"].string {
// someInt and message are available here
} else {
// someInt and message are not available
}
Or with guard:
guard let someInt = json["someInt"].int,
message = json["message"].string else {
// error, someInt and message are not available
return
}
// someInt and message are available here
Very simple, probably you already know it, you could protect your code with:
if let someInt = json["someInt"].int {
// do whatever you want with someInt
}
if let message = json["message"].string {
// do whatever you want with message
}
Try this approach:
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if let data = data,
jsonString = NSString(data: data, encoding: NSUTF8StringEncoding)
where error == nil {
var json = JSON(data: data!)
// use some protection as explained before..
} else {
print("error=\(error!.localizedDescription)")
}
}
task.resume()
Let me post my answer too =)
first of all you can implement small extension for failure JSON initializer:
extension JSON {
init?(_ data: NSData?) {
if let data = data {
self.init(data: data)
} else {
return nil
}
}
}
You may put it in global scope with SwiftyJSON imported and forget about forcing unwrap your data before use it in JSON. Same fail initializers can be written for other data types if you use them. Its only for a bit shorter and readable code in future. With many routes or in some cases, for example when you wait from json some single fields, this extension can make your code looks extremely easy and readable:
guard let singleMessage = JSON(data: data)?["message"].string else {return}
Then you need to check for nil in way that you need (in fact explained in previous answers). Probably you searching for fully valid data, so use if-let chain:
let myURL = NSURL(string: SERVER_URL);
let request = NSMutableURLRequest(URL:myURL!);
request.HTTPMethod = "POST";
let postString = ""
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
if error != nil {
print("error=\(error)")
return
}
dispatch_async(dispatch_get_main_queue()) {
if let json = JSON(data: data),
someInt = json["someInt"].int,
message = json["message"].string,
// ...
{
// all data here, do what you want
} else {
print("error=\(error)")
return
}
}
}
The best would be to handle using try catch
request.HTTPBody = postdata.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
(data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
var jsondata: AnyObject?
do
{
let jsondata = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
print(jsondata)
// your code here
}
catch
{
print("Some Error Found")
}
})
}
task.resume()
If you encounter any error, you will receive a message in the console, thus preventing the application from crashing

HTTP Get receive JSonObjects Swift DebugDescription=Invalid value around character 0

I'm getting an issue while sending an HTTP GET command to a server to retrieve JSONObjects.
here is the command:
if let url: NSURL = NSURL(string: "http://11.22.33.44:8080/SRV/getAllUsers?owner=\(User.sharedInstance.email)") {
print("\nSending URL: \(url)")
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:{
(response: NSURLResponse?, data: NSData?, error: NSError?)-> Void in
print("Response: \(response) \n")
do{
var datastring = NSString(data:data!, encoding:NSUTF8StringEncoding) as String?
print("Data: \(datastring)")
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
print("Json: \(json)")
}catch {
print("Error with Json: \(error)")
}
});
I received a HTTP 200 with all header information, but I'm trying to print NSData as String (nil) and also trying to retrieve my JSONObjects, I get the following message:
Data: nil
Error with Json: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
I'm managing the server part, the servlet which is preparing JSONObjects is doing the following:
ObjectOutputStream objOut = new ObjectOutputStream(response.getOutputStream());
JSONObject jsonObj = new JSONObject();
jsonObj.put("id","1234");
objOut.writeObject(jsonObj);
objout.flush();
jsonObj = new JSONObject();
jsonObj.put("id","5678");
objOut.writeObject(jsonObj);
objout.flush();
and a last important information, I'm able to retrieve those JSONObject from an Android application without any problem but it seems the format expected in swift for JSONObjects are not the same...
EDIT
I changed the way to send HTTP GET command by using NSURLSession but before treating the JSONObject, I'm trying at least to display data as String:
typealias Payload = [String: AnyObject]
let url = NSURL(string: "http://11.22.33.44:8080/SRV/getAllUsers?owner=\(User.sharedInstance.email)")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!) { (data, response, error) -> Void in
if(error == nil)
{
let err : NSError! = nil
print("Response \(response)")
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error")
return
}
let dataString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Data: \(dataString)")
var json: Payload!
// 1
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions()) as? Payload
print("JSon: \(json)")
} catch {
print(error)
//XCPlaygroundPage.currentPage.finishExecution()
}
}
else
{
print(error?.description)
}
}
task.resume()
I Received a HTTP 200 with the right header information, so I'm sure the servlet is successfully called, but get nil in data
Data: nil
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
EDIT #2
by using the following line
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error data")
return
}
print("data: \(data?.debugDescription)")
I can retrieve the following:
data: Optional("OS_dispatch_data: data[0x7fc68bc45380] = { composite, size = >1067, num_records = 5 record[0] = { from = 0, length = 404, data_object = >0x7fc68bc999d0 }, record[1] = { from = 0, length = 135, data_object = >0x7fc68be1f830 }, record[2] = { from = 0, length = 264, data_object = >0x7fc68bc99a80 }, record[3] = { from = 0, length = 133, data_object = >0x7fc68bf97c20 }, record[4] = { from = 0, length = 131, data_object = >0x7fc68bca0b40 }, }>")
means I am able to retrieve data (at least!) but I don't know how I can extract from this data my JSONObject....
SOLUTION
I finally found my problem.
server part needs to prepare JSONObject like this:
response.setContentType("application/json");
// Get the printwriter object from response to write the required json object to the output stream
PrintWriter out = response.getWriter();
// Assuming your json object is **jsonObject**, perform the following, it will return your json object
out.print(jsonObject);
out.flush();
instead of using ObjectOutPutStream.
Swift part can retrieve it like this:
let url_to_request = "http://11.22.33.44:8080/SRV/getAllUsers?owner=\(User.sharedInstance.email)"
let url:NSURL = NSURL(string: url_to_request)!
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
request.timeoutInterval = 10
let task = session.dataTaskWithRequest(request) {
(
let data, let response, let error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
print("error data")
return
}
var json: AnyObject?
do
{
json = try NSJSONSerialization.JSONObjectWithData(data, options: [])
for anItem in json as! [Dictionary<String, AnyObject>] {
let nom = anItem["nom"] as! String
let prenom = anItem["prenom"] as! String
let id = anItem["id"] as! String
print("nom: \(nom) prenom: \(prenom) id: \(id)")
}
}
catch
{
print("error Serialization")
return
}
}
task.resume()

Create and send json data to server using swift language and iOS 9+

I really need a code for send and receive data from server with JSON, i find a really good code but it isn't compatible with iOS9.
#IBAction func submitAction(sender: AnyObject) {
//declare parameter as a dictionary which contains string as key and value combination.
var parameters = ["name": nametextField.text, "password": passwordTextField.text] as Dictionary<String, String>
//create the url with NSURL
let url = NSURL(string: "http://myServerName.com/api") //change the url
//create the session object
var session = NSURLSession.sharedSession()
//now create the NSMutableRequest object using the url object
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST" //set http method as POST
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &err) // pass dictionary to nsdata object and set it as request body
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
//create dataTask using the session object to send data to the server
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume() }
Really thanks for the help
Swift syntax changed a little bit, but not significantly to break the whole code.
You will need to adjust few things like
println(err!.localizedDescription)
to
print(err!.localizedDescription)
Then your code will compile
Maybe have a look into the Alamofire Framework.
It really is making your life easier when it comes to handling HTTP requests.
Otherwise, as vadian suggested, check out the Swift 2 (do-try-catch) Errorhandling.
I have found a great tutorial Project from deege.
https://github.com/deege/deegeu-swift-rest-example
Here a breakdown of a HTTP request.
// Setup the session to make REST GET call. Notice the URL is https NOT http!! (if you need further assistance on how and why, let me know)
let endpoint: String = "https://yourAPI-Endpoint"
let session = NSURLSession.sharedSession()
let url = NSURL(string: endpoint)!
// Make the call and handle it in a completion handler
session.dataTaskWithURL(url, completionHandler: { ( data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
// Make sure we get an OK response
guard let realResponse = response as? NSHTTPURLResponse where
realResponse.statusCode == 200 else {
print("Not a 200 response")
return
}
// Read the JSON
do {
if let jsonString = NSString(data:data!, encoding: NSUTF8StringEncoding) {
// Print what we got from the call
print(jsonString)
// Parse the JSON
let jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
let value = jsonDictionary["key"] as! String
}
} catch {
print("bad things happened")
}
}).resume()

Making a re-useable function of JSON URL fetching function in SWIFT 2.0

I am stuck in a problem. I think it is all due to my weak basics. I am sure someone can help me easily and put me in the right direction.
I have different segues and all get the data from JSON via remote URL.
So in-short all segues need to open URL and parse JSON and make them into an ARRAY
I have made the first segue and it is working fine.
Now i plan to use the functions where it download JSON and turns it into ARRAY as a common function
I read in another page on stackoverflow that I can declare all common functions outside the class in ViewController
I hope everyone is with me this far.
now in ViewController i declare a function
getDataFromJson(url: String)
This function code looks like following
func getJsonFromURL(url: String)
{
// some class specific tasks
// call the common function with URL
// get an array
let arrJSON = getJsonArrFromURL(url)
for element in arrJSON
{
// assign each element in json to ur table
print("Element: \(element)")
}
// some class specific tasks
}
and this will call the common function declared outside the score of class
getArrFromJson(url: String) -> NSArray
This common function is just very generic.
Take a URL, call it, open it, parse its data into ARRAY and return it back.
The problem i am stuck is where to put the return
It returns empty array as the task is not finished and i am clueless
func getJsonArrFromURL(var url: String) -> NSArray
{
var parseJSON : NSArray?
if ( url == "" )
{
url = self.baseURLHomepage
}
print("Opening a JSON URL \(url)")
let myUrl = NSURL(string: url);
let request = NSMutableURLRequest(URL:myUrl!);
request.HTTPMethod = "GET";
let postString = "";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request)
{
data, response, error in
if ( error != nil )
{
print("Error open JSON url \n\(error)")
return
}
do
{
parseJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSArray
}
catch
{
self.showAlert("Error", msg: "Error occurred while trying to process the product information data")
print("Error occured in JSON = \(error)")
}
}
task.resume()
return parseJSON!
}
You can probably add a method like below in any of your class
func post(url: String, info: String, completionHandler: (NSString?, NSError?) -> ()) -> NSURLSessionTask {
let URL = NSURL(string: url)!
let request = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "GET"
let bodyData = info
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
dispatch_async(dispatch_get_main_queue()) {
guard data != nil else {
print("response String is nil")
completionHandler(nil, error)
return
}
if let dataNew = data {
completionHandler(NSString(data: (NSData(base64EncodedData: dataNew, options: NSDataBase64DecodingOptions([])))!, encoding: NSASCIIStringEncoding), nil)
}
}
}
task.resume()
return task
}
and access it anywhere like
let url = "your URL String"
let info = "The data you would like to pass"
yourClassName.post(url, info: info) { responseString, error in
guard responseString != nil else {
print("response String is nil")
print(error)
return
}
do {
if !(responseString as? String)!.isEmpty {
let json = try NSJSONSerialization.JSONObjectWithData((responseString as! String).data, options: NSJSONReadingOptions.init(rawValue: 0))
//process your json here
}
} catch {
print("Error\n \(error)")
return
}
}
Extend your string like follows
extension String {
var data:NSData! {
return dataUsingEncoding(NSUTF8StringEncoding)
}
}

Resources