1

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! :-)

1
  • Do you have any error, what do you get into questionOne variable? Commented Jan 19, 2015 at 9:07

2 Answers 2

1

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!

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! i'm trying to adapt this code to se if it works. But I get an error with dlog, So I guess i need to initialize it before use? String didn't work and gave me an error that the variable is not a string.
Im sorry the dog is my own debug log function, i Eddited my answer to replace it with println() sorry for that. :) Let me know if you have any other problems. Or better yet if you can better the code!
And about the strings, just check the JSON structure. Does "let correctAnswer = (parsedData! as NSDictionary).objectForKey("correctAnswer")" not work?
Thank you very much for the effort! It almost solved my problem, but no cigar this time. :-)
0

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

1 Comment

Thank you! I'm so close right now! I think you have the solution! Im just trying to figure out som small things regarding the newQuestion array and adapt it to my questionTemplate. Right now im getting an error: /Users/christopherottesen/Documents/Git/TKquiz/Quiz App/Quiz App/ViewController.swift:119:45: '(String, answerOne: String, answerTwo: String, answerThree: String, answerFour: String, correctAnswer: String) -> $T7' is not identical to 'NSArray' also I have updated my OP withthe full questionTemplate

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.