make a button display an element each time its pressed - swift

I am new to Swift, and I am trying to make a basic question answer app. I want to set up the question button so that whenever I press it, it displays one question, and if I press it again, it shows another question. I have a separate button that will show the answer but I need to connect to which ever question is being asked. How do I do this?
Here is what I have so far, it just asks the question at random, but I want to be able to ask all the questions, not just whatever it picks, I am not sure how to do that though.
#IBAction func question(_ sender: Any) {
let questions = ["What is your name?", "What is your favourite colour?",
"What is your favourite movie?", "What is your major?"]
let randomQuestion = questions.randomElement()
qLabel.text = randomQuestion
}

You can try
var index = 0 // add a current index of the shown question
let questions = ["What is your name?", "What is your favourite colour?",
"What is your favourite movie?", "What is your major?"]
#IBAction func question(_ sender: Any) {
if index < questions.count {
qLabel.text = questions[index]
index += 1
}
else {
// end of questions
}
}

Related

Swift, increment a number on each button tap

I have created an app where I am uploading data to a database. However, I want to assign a specific key to each entry. For example, if the user is making their first entry into db. The key name would be "Entry 1", if they make a second entry, it would be "Entry 2". This is what I tried, but its not working.
#IBAction func doSomething(_ sender: Any) {
var keyCounter = 0
keyCounter = keyCounter + 1
print("Key Counter = ",keyCounter)
}
Here is the output of me pressing the button 3 times. Expected output: Key Counter = 3
Actual output:
I know that whenever I press the button its re-initializing the value of the counter to 0. I am not sure what the best way to approach this is. Any guidance or help would be appreciated.
Do something like this:
class FooViewController: UIViewController {
var keyCounter = 0
#IBAction func doSomething(_ sender: Any) {
keyCounter = keyCounter + 1
print("Key Counter = ",keyCounter)
}
}

How to solve this Swift problem (AP CP Principles - Structures)

I am currently going through Apple Curriculum books and stumbled across a problem I can't figure out.
There is a structure:
struct Song {
let title: String
let artist: String
let duration: Int
var longestSong = false
}
and an array with 4 songs that have different duration: 90, 200, 150, 440.
The book asks to add a method that checks whether one song is longer than the other.
So, based on previous material I added the following method to my struct:
func isLongerThan(_ song: Song) -> Bool {
return duration > song.duration
}
}
Then the book asks to use a loop in order to find the longest song in the array and print it to the console
(Hint: use a variable to keep track of the longest song and initialize
it to the first one in the array.)
So, I came up with this loop:
for (index, _) in songs.enumerated() {
if index < songs.count-1{
if songs[index].isLongerThan(songs[index + 1]){
songs[index].longestSong = true
print("\(songs[index].title) is longer than \(songs[index+1].title)")
}
} else {
if songs[songs.count-1].isLongerThan(songs[0]){
songs[songs.count-1].longestSong = true
print("\(songs[songs.count-1].title) is longer than \(songs[0].title)")
}
}
}
The next step is to compare those songs with longestSong = true variable until only one song remains. But this isn't a good solution in my opinion.
Is there a better and more elegant way to solve this problem?
UPD
It seems that I have misread the instructions and have gone the wrong way.
With some help I managed to find this solution:
func searchForLongestSong(songs: [Song]) {
var lngstSongIndex = 0
for song in 0..<songs.count {
if songs[song].duration > songs[lngstSongIndex].duration {
lngstSongIndex = song
}
}
print("The longst song is \"\(songs[lngstSongIndex].title)\"")
}
searchForLongestSong(songs: songs)
Since it is an Array you can keep track of the "longest song" by saving the index of the longest song.
Create an Int var to save the index.
Loop through the indices for n in 0..<songs.count
if the duration of songs[n] is greater than songs[largestSongIdx]
Then update the longestSong variables for both accordingly

Swift make user selection on picker view the title for a button

So, I'm not sure if I've been staring at my code so long I've become dumb or if this is a bit too advanced for my current skills. I am trying to make a pickerview pop up when the user presses a button using DPPickerManager and when the user selects a color the title of the button is supposed to change to what was selected by the user. Flowing the directions I was able to link the button and pickerview but I can't get the button title to change. Here's my code:
#IBAction func colorPicker(_ sender: UIButton) {
let condition = ["Blue", "Black", "Green", "Orange", "Purple"]
DPPickerManager.shared.showPicker(title: "Strings Picker", selected: "Value 1", strings: condition) { (value, ind, cancel) in
if !cancel {
//sender.titleLabel.text = value![index].text
print(value as Any)
}
}
}
I keep getting this error: Cannot convert value of type '(Any) -> Int' to expected argument type '(UnboundedRange_) -> ()' and I think its because of the value's index but I am unsure. Can someone please help me?
I have used your code and it's working fine for me.
#IBAction func btnActionTapped(_ sender: UIButton) {
let condition = ["Blue", "Black", "Green", "Orange", "Purple"]
DPPickerManager.shared.showPicker(title: "String Picker", selected: "Value 1", strings: condition) { (value, index, cancel) in
if !cancel {
if let value = value {
sender.setTitle(value, for: .normal)
print(value)
}
}
}
}
I just changed following code to get value instead of optional value.
if let value = value {
print(value)
}
I’m getting string value there and print fine in console.

Xcode Swift: Converting Arrayed String With If Statement

This is a simple quiz app with a label and four buttons. I want code in the action button to execute by referencing the question in the if statement. (The problem with referencing the answer tag is that there are only four buttons, but more than four questions.) The code below gives an error that you can't use the binary operator. How can I make this work?
struct Question {
var Question : String!
var Answers : [String]!
var Answer : Int!
}
var Questions = [Question]()
var QNumber = Int()
var AnswerNumber = Int()
Questions = [Question(Question: "One", Answers: ["", "", "", ""], Answer: 0),
Question(Question: "Two", Answers: ["", "", "", ""], Answer: 1),
Question(Question: "Three", Answers: ["", "", "", ""], Answer: 2),
Question(Question: "Four", Answers: ["", "", "", ""], Answer: 3),
Question(Question: "Five", Answers: ["", "", "", ""], Answer: 0),]
func PickQuestion(){
if Questions.count > 0{
QNumber = 0
QLabel.text = Questions[QNumber].Question
AnswerNumber = Questions[QNumber].Answer
for i in 0..<Buttons.count{
Buttons[i].setTitle(Questions[QNumber].Answers[i], for: UIControlState.normal)
}
Questions.remove(at: QNumber)
}
#IBAction func Btn4(_ sender: Any) {
if(Question == "Five") {
//CODE THAT NEEDS TO EXECUTVE
} else if(Question == "Four") {
//EXECUTE A DIFFERENT CODE
}
Your question is super unclear and it looks like you would benefit from re-structuring your logic. That said, if this is a simple quiz app and you have a few buttons with tags 0, 1, 2 and 3 then you should simply be able to compare the Question's Answer property with the buttons tag and avoid comparing any strings altogether.
It's also not clear from your question how the "current question" is selected, so you may want to firm that one up too, I'd recommend storing the object in a var somewhere so you can do something like the following...
var currentQuestion:Question!
// Get the first question or something.
currentQuestion = Questions.first
#IBAction func buttonTapped(sender: UIButton) {
if sender.tag == currentQuestion.Answer {
print("You are a winner")
// Time to get a new question son.
}
}
The above code is untested and I hope it doesn't just confuse you further, however, in the current format your question may be closed as it is not completely clear what you are asking.
Edit:
Thanks for updating your question, It looks now like you are trying to compare the Question struct against the String "Five". these two objects are not comparable.
To make your code work you should use the AnswerNumber variable that you have made and check if the number matches like so.
#IBAction func Btn4(_ sender: Any) {
if AnswerNumber == 4 {
print("Correct Answer")
//CODE THAT NEEDS TO EXECUTVE
} else {
print("Wrong Answer")
//EXECUTE DIFFERENT CODE
}
}
Assuming you have an IBAction for each button you will need to repeat this for each, so Btn5 would look like this.
#IBAction func Btn5(_ sender: Any) {
if AnswerNumber == 5 {
...
Edit:
After chatting away, we figured out that you needed a custom action for each question (if the correct answer was selected). this took the form of an mp3 file that was played depending on which question it was.
We came to the conclusion that following the existing structure you should add another variable to hold the mp3 in the Question struct but also for the current question as below.
struct Question {
var Question : String!
var Answers : [String]!
var Answer : Int!
var audioFile: String!
}
var AnswerMP3 = ""
Then when we set the current question alongside AnswerNumber we can set the mp3 like so.
AnswerMP3 = Questions[QNumber].audioFile
Then in this way you do not need to have hardcoded actions for each question. the buttons simply pass the correct mp3 on to another method that plays the audio file.
if AnswerNumer == 4 {
playMP3File(AnswerMP3)
}
func playMP3File(fileName:String) {
// user the fileName to play the audio file.
}

textual questionnaire system - swift 3

This question is about building a textual questionnaire system using swift 3.
Assuming we have (n) questions, the user will be asked one question at the time, replying with text (using UITextField).
if the answer is something that is expected (YES/NO for example) the code will carry on to the next question, otherwise it will try to give some more elaborate question with possible answers (see code below).
The idea is having some kind of an array of dictionaries, each dictionary (questionItem) contains a single question/answer data...
Question: even if the following code works fine, I feel that this is not the most scalable nor elegant solution. Thus my question is more about your ideas regarding code design.
how can one make a code such as this - that is scalable for multiple questions.
static var questionItem = [
"question": "Is the sky blue?",
"answer": "yes",
"afterAnswer": "question #2",
"explanation": "simply answer: yes or no"
]
class func getAnswer(answer: String) -> String
{
let expectedAnswer = questionItem["answer"]
let isEqual = (answer == expectedAnswer)
var respond = "undifined"
if isEqual {
// go for next question ( questionItem["afterAnswer"] )
respond = "ok, going to the next question"
} else {
// didn't got the answer I was waiting for, going to show some longer explanation
respond = questionItem["explanation"]!
}
// respond
return respond
}
You can create a struct with your desired information, then create a Trivia of Type Int: YourStruct to manage all the different questions answers and explanations, like my example below, let me know is its clear enough:
struct QuestionsAndAnswers{
var question: String = ""
var answer: String = ""
var explanation: String = ""
}
var trivia: [Int: QuestionsAndAnswers] = [:]
trivia = [1: QuestionsAndAnswers.init(question: "Your First Question", answer: "Your Fist Answer", explanation: "Your First explanation")]
trivia = [2: QuestionsAndAnswers.init(question: "Your Second Question", answer: "Your Second Answer", explanation: "Your Second explanation")]
func getAnswer(answer: String, quesiontNumber: Int) -> String
{
let expectedAnswer = trivia[quesiontNumber]?.answer
let isEqual = (answer == expectedAnswer)
var respond = "undifined"
if isEqual {
// go for next question ( questionItem["afterAnswer"] )
respond = "ok, going to the next question"
} else {
// didn't got the answer I was waiting for, going to show some longer explanation
respond = (trivia[quesiontNumber]?.explanation)!
}
// respond
return respond
}