0

This is the struct of my array:

struct Question {
    let imgName: String
    let questionText: String
    let options: [String]
    let correctAns: Int
    var wrongAns: Int
    var isAnswered: Bool
}

var questionsArray = [Question]()

Here is how the array is populated currently:

let que1 = Question(imgName: "img1", questionText: "What is 2 x 2 ?", options: ["2", "4", "8", "6"], correctAns: 1, wrongAns: -1, isAnswered: false)
let que2 = Question(imgName: "img2", questionText: "What is 4 + 2 ?", options: ["9", "4", "3", "6"], correctAns: 3, wrongAns: -1, isAnswered: false)
questionsArray = [que1, que2]

I would like to put data in a text file and populate my questionsArray. So I created a file, data.txt and put it into bundle. Below is the content of data.txt. Each question is separated by a new line.

Question(imgName: "img1", questionText: "What is 2 x 2 ?", options: ["2", "4", "8", "6"], correctAns: 1, wrongAns: -1, isAnswered: false)
Question(imgName: "img2", questionText: "What is 4 + 2 ?", options: ["9", "4", "3", "6"], correctAns: 3, wrongAns: -1, isAnswered: false)

I tried to use this method:

var arrayOfStrings: [String]?

do {
    if let path = Bundle.main.path(forResource: "data", ofType: "txt") {
        let data = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
        arrayOfStrings = data.components(separatedBy: "\n")
        questionsArray = arrayOfStrings
    }
} catch let err as NSError {
    print(err)
}

However, I received an error, Cannot assign value of type '[String]?' to type '[Question]' for the line questionsArray = arrayOfStrings.

How to solve this?

3
  • Your arrayOfStrings is not yet set to an array of Question objects. So you try to set a [String] type to a variable of type [Question]. arrayOfStrings need to be first converted back to [Question] Commented May 2, 2018 at 12:05
  • 4
    arrayOfString is [String] and questionsArray is [Question]. The types clearly don't match. That's what the error message says. How are the single lines organized to separate the fields? I highly recommend to save the data as JSON or Property List and decode it directly into the struct. Commented May 2, 2018 at 12:06
  • Your questionsArray is array of Question struct and you are assigning array of string directly to array of your struct questionsArray. Commented May 2, 2018 at 12:07

2 Answers 2

1

This is a quick tutorial for a better data management. It uses widely your code.

  • Create a new Blank Playground, platform macOS (important!). You can keep the playground to add more questions.
  • Paste this code, it creates a JSON file questions.json on the desktop

    struct Question : Encodable {
        let imgName: String
        let questionText: String
        let options: [String]
        let correctAns: Int
        var wrongAns: Int
        var isAnswered: Bool
    }
    
    let que1 = Question(imgName: "img1", questionText: "What is 2 x 2 ?", options: ["2", "4", "8", "6"], correctAns: 1, wrongAns: -1, isAnswered: false)
    let que2 = Question(imgName: "img2", questionText: "What is 4 + 2 ?", options: ["9", "4", "3", "6"], correctAns: 3, wrongAns: -1, isAnswered: false)
    let questionsArray = [que1, que2]
    
    do {
        let jsonData = try JSONEncoder().encode(questionsArray)
        let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop/questions.json")
        try jsonData.write(to: url)
    } catch {
        print(error)
    }
    
  • Drag the file from the desktop into your project navigator. Make sure that Copy if needed is checked.

  • Use this code in your project

    struct Question : Decodable {
        let imgName: String
        let questionText: String
        let options: [String]
        let correctAns: Int
        var wrongAns: Int
        var isAnswered: Bool
    }
    
    var questionsArray = [Question]()
    
    
    let url = Bundle.main.url(forResource: "questions", withExtension: "json")!
    let data = try! Data(contentsOf: url)
    questionsArray = try! JSONDecoder().decode([Question].self, from: data)
    
Sign up to request clarification or add additional context in comments.

Comments

0

Saving the data in a file is a good idea. But in the format of txt and especially in this format below is definitely not a good idea :

Question(imgName: "img1", questionText: "What is 2 x 2 ?", options: ["2", "4", "8", "6"], correctAns: 1, wrongAns: -1, isAnswered: false)

You should use the json format which is perfectly suitable for this case. You save the data into a file.json.

How to do it ? Add the Codable protocol to your struct Question:

struct Question: Codable {
    let imgName: String
    let questionText: String
    let options: [String]
    let correctAns: Int
    var wrongAns: Int
    var isAnswered: Bool
}

Then encode the data :

do {
    let encodedData = try JSONEncoder().encode(questionsArray)
    // Write encoded data to file
} catch let err {
    print(err)
}

And when you want retrieve back the data:

let data = Data(contentsOf: url)
do {
    let decodedData = try JSONDecoder().decode([Question].self, from: data)
} catch let err {
    // Failed to decode data
    print(err)
}

Comments

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.