Unresolved Identifier 'count' - swift

Here is the error that I am seeing.
The "cardButton" is responsible for showing the next question. This is a small card app game that I am trying to make and as you can see from the image this is where I am having the issue with the code.
Here is the code:
import UIKit
class MultipleViewController: UIViewController {
#IBOutlet weak var questionLabel2: UILabel!
#IBOutlet var answerButtons: [UIButton]!
#IBOutlet weak var cardButton: UIButton!
#IBAction func cardButtonHandle(_ sender: Any) {
cardButton.isEnabled = true
if questionIdx < count(mcArray) - 1 { // There are still more questions
questionIdx += 1 //
} else {
questionIdx = 0
}
nextQuestion()
}
#IBAction func answerButtonHandle(_ sender: UIButton) {
if sender.titleLabel?.text == correctAnswer{
sender.backgroundColor = UIColor.green
print("Correct!")
} else {
sender.backgroundColor = UIColor.red
print("Wrong Answer")
}
for button in answerButtons{
button.isEnabled = false
if button.titleLabel?.text == correctAnswer {
button.backgroundColor = UIColor.green
}
}
cardButton.isEnabled = true // next question
}
var correctAnswer: String? // correct answers
var answers = [String]() // answers
var question : String? // Questions
var questionIdx = 0 // not sure what this is ?
override func viewDidLoad() {
super.viewDidLoad()
// titleForButtons() // call buttons as soon its loaded..
cardButton.isEnabled = false
nextQuestion()
}
func nextQuestion (){
let currentQuestion = mcArray![questionIdx]
answers = currentQuestion["Answers"] as! [String]
correctAnswer = currentQuestion["CorrectAnswer"] as? String
question = currentQuestion["Question"] as? String
titleForButtons ()
}
func titleForButtons (){
for (idx,button) in answerButtons .enumerated() {
button.titleLabel?.lineBreakMode = .byWordWrapping
button.setTitle(answers[idx],for:.normal)
button.isEnabled = true
}
questionLabel2.text = question
}
}

The following should work, you did not have the correct syntax for the length of the array. Note that if you have not initialized your questions array, this would cause a crash. Therefore you might want to add a guard into your code. Perhaps use the following
#IBAction func cardButtonHandle(_ sender: Any) {
cardButton.isEnabled = true
if questionIdx < (mcArray!.count) - 1 { // There are still more questions
questionIdx += 1 //
} else {
questionIdx = 0
}
nextQuestion()
}

Related

QUIZ app ... UIAlertController not coming up and not restarting back to initial question

The nextQuestion() and the startOver() function I believe is where it is giving me trouble... when I go through the questions it get to the end and does not pop up the alert on the screen just have to hit the True or false one and then it will startOver() but then it skips the first one and goes directly to the second question
import UIKit
class ViewController: UIViewController {
//Place your instance variables here
let allQuestions = QuestionBank()
var pickedAnswer : Bool = false
var questionNumber : Int = 0
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet var progressBar: UIView!
#IBOutlet weak var progressLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let firstQuestion = allQuestions.list[0]
questionLabel.text = firstQuestion.questionText
//when app loads it will display the first question in the array of question bank
}
#IBAction func answerPressed(_ sender: AnyObject) {
if sender.tag == 1 {
pickedAnswer = true
}
else if sender.tag == 2 {
pickedAnswer = false
}
//above - will change the picked answer based on which tag # is pressed
checkAnswer()
questionNumber = questionNumber + 1
nextQuestion()
}
func updateUI() {
}
func nextQuestion() {
if questionNumber <= 12 {
questionLabel.text = allQuestions.list[questionNumber].questionText
//if the current questionNumber is equal to or less than 12 then it will change the display text to the current question
}
else {
let alert = UIAlertController(title: "Congrats!", message: "Do you want to restart?", preferredStyle: .alert)
let restartAction = UIAlertAction(title: "Restart", style: .default, handler: { UIAlertAction in
self.startOver()
})
alert.addAction(restartAction)
present(alert, animated: true, completion: nil)
}
}
func checkAnswer() {
let correctAnswer = allQuestions.list[questionNumber].answer
if correctAnswer == pickedAnswer {
print("You got it!")
}
else {
print("Wrong!")
}
}
func startOver() {
questionNumber = 0
nextQuestion()
}
}
its a firmware issues. just updated to the latest IOS 13 update and the simulator ran the app no issues so I believe it is with my firmware being the latest versus Xcode with the previous one. it ran no issues on the simulator. simulator on 13.1.1 and I just uploaded to 13.1.3 that's the only difference. I had looked at the completed app from the course and its all line for line the same except the firmware.app running on Xcode simulator

Swipe left and right between Core Data with a label

I hope you can help.
There is a label and when any user swipe on it. It will make a call to core data and show values on label. Data will depend upon gesture. If its left/right data will be different on each time. Below is the code that i have written. Please suggest whether its correct or not?
class ViewController: UIViewController {
var helloArray = [Tasks]()
var currentArrayIndex = 0
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var helloLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.handleSwipes(sender:)))
let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.handleSwipes(sender:)))
leftSwipe.direction = .left
rightSwipe.direction = .right
view.addGestureRecognizer(leftSwipe)
view.addGestureRecognizer(rightSwipe)
ouputData()
}
#objc func handleSwipes(sender: UISwipeGestureRecognizer) {
if sender.direction == .left {
currentArrayIndex = (currentArrayIndex + 1) % 3
}
}
func ouputData() {
do {
helloArray = try context.fetch(Tasks.fetchRequest())
for each in helloArray {
helloLabel.text = each.name
}
} catch {
}
appDelegate.saveContext()
}
#IBAction func btnPressed(_ sender: Any) {
let infoTasks = Tasks(context: context)
infoTasks.name = textField.text
appDelegate.saveContext()
do {
try context.save()
} catch {
print("Error")
}
textField.text = ""
}
}
I think you need to modify your handleSwipes and outputData function.
You outputData should only fetch all the data from CD in viewDidload.
Once you have the data source you can fetch item from source and populate your helloLabel based on index.
#objc func handleSwipes(sender: UISwipeGestureRecognizer) {
if sender.direction == .left {
currentArrayIndex = (currentArrayIndex + 1) % 3
} else if sender.direction == .right {
currentArrayIndex = (currentArrayIndex - 1) % 3
}
helloLabel.text = helloArray[currentArrayIndex].name
}
And:
func ouputData() {
do {
helloArray = try context.fetch(Tasks.fetchRequest())
} catch {
}
appDelegate.saveContext()
}
Hope it helps.

How can I get the game to show the word after all guesses have been used up?

so I'm new to coding and I've been doing practice games a such to build my skills. I've created this word guessing game and I'm trying to make the game show the word after all guesses have been used up. However, the program doesn't read the code I write to set the label to display the answer. Here is the code I've written so far:
class ViewController: UIViewController {
var listOfWords = ["ladybug", "program", "computer", "language", "glorious", "incandescent"]
let incorrectMovesAllowed = 7
var totalWins = 0 {
didSet {
newRound()
}
}
var totalLosses = 0 {
didSet {
newRound()
}
}
#IBOutlet var letterButtons: [UIButton]!
#IBAction func buttonPressed(_ sender: UIButton) {
sender.isEnabled = false
let letterString = sender.title(for: .normal)!
let letter = Character(letterString.lowercased())
currentGame.playerGuessed(letter: letter)
updateUI()
updateGameState()
}
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet weak var correctWordLabel: UILabel!
#IBOutlet weak var treeImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
newRound()
// Do any additional setup after loading the view, typically from a nib.
}
func enableLetterButtons (_enable: Bool){
for button in letterButtons {
button.isEnabled = _enable
}
}
var currentGame : Game!
func newRound() {
if !listOfWords.isEmpty{
let newWord = listOfWords.removeFirst()
currentGame = Game (word: newWord, incorrectMovesRemaining: incorrectMovesAllowed, guessedLetters: [])
enableLetterButtons(_enable: true)
updateUI()
} else {
enableLetterButtons (_enable: false)
}
}
func updateUI() {
var letters = [String] ()
for letter in currentGame.formattedWord.characters {
letters.append(String(letter))
}
let wordWithSpacing = letters.joined(separator: " ")
correctWordLabel.text = wordWithSpacing
scoreLabel.text = "Wins: \(totalWins), Losses:\(totalLosses)"
treeImageView.image = UIImage (named: "Tree \(currentGame.incorrectMovesRemaining)")
}
func updateGameState(){
var letters = [String] ()
for letter in currentGame.word.characters {
letters.append(String(letter))
}
let theAnswer = letters.joined(separator: " ")
if currentGame.incorrectMovesRemaining == 0 {
correctWordLabel.text = theAnswer
Thread.sleep(forTimeInterval: 3)
totalLosses += 1
} else if currentGame.word == currentGame.formattedWord {
totalWins += 1
} else {
updateUI()
}
}
}
In addition, I have a structure that is written like this:
import Foundation
struct Game {
var word : String
var incorrectMovesRemaining : Int
var guessedLetters: [Character]
mutating func playerGuessed (letter: Character){
guessedLetters.append(letter)
if !word.characters.contains(letter){
incorrectMovesRemaining -= 1
}
}
var formattedWord: String {
var guessedWord = ""
for letter in word.characters {
if guessedLetters.contains(letter) {
guessedWord += "\(letter)"
} else {
guessedWord += "_"
}
}
return guessedWord
}
}
You need to redraw your UI, this is done with self.setNeedsDisplay(). It notifies the system that the view's contents needs to be redrawn. In your updateUI() you can add this.
Regarding setNeedsDisplay you can get more information here
class ViewController: UIViewController {
var listOfWords = ["ladybug", "program", "computer", "language", "glorious", "incandescent"]
let incorrectMovesAllowed = 7
var totalWins = 0 {
didSet {
newRound()
}
}
var totalLosses = 0 {
didSet {
newRound()
}
}
#IBOutlet var letterButtons: [UIButton]!
#IBAction func buttonPressed(_ sender: UIButton) {
sender.isEnabled = false
let letterString = sender.title(for: .normal)!
let letter = Character(letterString.lowercased())
currentGame.playerGuessed(letter: letter)
updateUI()
updateGameState()
}
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet weak var correctWordLabel: UILabel!
#IBOutlet weak var treeImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
newRound()
// Do any additional setup after loading the view, typically from a nib.
}
func enableLetterButtons (_enable: Bool){
for button in letterButtons {
button.isEnabled = _enable
}
}
var currentGame : Game!
func newRound() {
if !listOfWords.isEmpty{
let newWord = listOfWords.removeFirst()
currentGame = Game (word: newWord, incorrectMovesRemaining: incorrectMovesAllowed, guessedLetters: [])
enableLetterButtons(_enable: true)
updateUI()
} else {
enableLetterButtons (_enable: false)
}
}
func updateUI() {
var letters = [String] ()
for letter in currentGame.formattedWord.characters {
letters.append(String(letter))
}
let wordWithSpacing = letters.joined(separator: " ")
correctWordLabel.text = wordWithSpacing
scoreLabel.text = "Wins: \(totalWins), Losses:\(totalLosses)"
treeImageView.image = UIImage (named: "Tree \(currentGame.incorrectMovesRemaining)")
self.setNeedsDisplay()
}
func updateGameState(){
var letters = [String] ()
for letter in currentGame.word.characters {
letters.append(String(letter))
}
let theAnswer = letters.joined(separator: " ")
if currentGame.incorrectMovesRemaining == 0 {
correctWordLabel.text = theAnswer
Thread.sleep(forTimeInterval: 3)
totalLosses += 1
} else if currentGame.word == currentGame.formattedWord {
totalWins += 1
} else {
updateUI()
}
}
}
Create a variable that will keep track of how many times you have guessed wrong. Then you can do this:
Use a while statement:
while numberOfTimesGuessedWrong <= 7{
}
//when you have guessed incorrectly 7 times, the compiler will move here:
wordLabel.text = "\(correctAnswer)"
So when you guess incorrectly 7 times, on the 8th time, it will then show the correct answer.

How to keep track of items answered on in a label?

In my quiz app, if I wanted to keep track of the question number the user was on and display it, how would I do so with my following code? So if the user has answered two questions when the third appears I want it to display "question number 3". Basically I want the user to know what number question they are on and it should be equivalent to the number of questions they've answered plus one.
Here's my code:
import UIKit
class ViewController: UIViewController {
var questionList = [String]()
func updateCounter() {
counter -= 1
questionTimer.text = String(counter)
if counter == 0 {
timer.invalidate()
wrongSeg()
}
}
func randomQuestion() {
//random question
if questionList.isEmpty {
questionList = Array(QADictionary.keys)
}
let rand = Int(arc4random_uniform(UInt32(questionList.count)))
questionLabel.text = questionList[rand]
//matching answer values to go with question keys
var choices = QADictionary[questionList[rand]]!
questionList.remove(at: rand)
//create button
var button:UIButton = UIButton()
//variables
var x = 1
rightAnswerBox = arc4random_uniform(4)+1
for index in 1...4
{
button = view.viewWithTag(index) as! UIButton
if (index == Int(rightAnswerBox))
{
button.setTitle(choices[0], for: .normal)
}
else {
button.setTitle(choices[x], for: .normal)
x += 1
}
}
randomImage()
}
let QADictionary = ["Who is Thor's brother?" : ["Atum", "Loki", "Red Norvell", "Kevin Masterson"], "What is the name of Thor's hammer?" : ["Mjolinr", "Uru", "Stormbreaker", "Thundara"], "Who is the father of Thor?" : ["Odin", "Sif", "Heimdall", "Balder"]]
//wrong view segue
func wrongSeg() {
performSegue(withIdentifier: "incorrectSeg", sender: self)
}
//proceed screen
func rightSeg() {
performSegue(withIdentifier: "correctSeg", sender: self)
}
//variables
var rightAnswerBox:UInt32 = 0
var index = 0
//Question Label
#IBOutlet weak var questionLabel: UILabel!
//Answer Button
#IBAction func buttonAction(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerBox))
{
rightSeg()
timer.invalidate()
print ("Correct!")
}
if counter != 0 {
counter = 15
}
else if (sender.tag != Int(rightAnswerBox)) {
wrongSeg()
print ("Wrong!")
timer.invalidate()
questionList = []
}
}
override func viewDidAppear(_ animated: Bool)
{
randomQuestion()
questionTimer.text = String(counter)
timer = Timer.scheduledTimer(timeInterval: 1, target:self, selector: #selector(ViewController.updateCounter), userInfo: nil, repeats: true)
}
//variables
var counter = 15
var timer = Timer()
#IBOutlet weak var questionTimer: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
Take counter for total number of question globally and update it in random question like
var answerdQuestion = 1;
func randomQuestion() {
//random question
if questionList.isEmpty {
questionList = Array(QADictionary.keys)
}
lblQuestionNumber.text = Strint(answerdQuestion)
answerdQuestion += 1
:
:
}

I need help debugging this error - Maths Quiz for Kids

My school project is a children's maths game where it test them in addition, subtraction and multiplication. I have two VC's that are linked to the error. The error I keep having is that every time I choose any of the options it ignores all the other operations and follows the instructions for multiplication! I have tried everything and I'm getting frustrated with this application.
Option_VC
class Option_VC: UIViewController {
var addition_true: Bool = false
var subtract_true: Bool = false
var multiply_true: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if addition_true == true {
let nextVC: Quiz_VC = segue.destinationViewController as! Quiz_VC
nextVC.addition_true = true
}else if subtract_true == true {
let nextVC: Quiz_VC = segue.destinationViewController as! Quiz_VC
nextVC.subtract_true = true
}else {
let nextVC: Quiz_VC = segue.destinationViewController as! Quiz_VC
nextVC.multiply_true = true
}
}
#IBAction func addition_enter(sender: AnyObject) {
addition_true = true
multiply_true = false
subtract_true = false
}
#IBAction func subtract_enter(sender: AnyObject) {
subtract_true = true
addition_true = false
multiply_true = false
}
#IBAction func multiply_enter(sender: AnyObject) {
multiply_true = true
addition_true = false
subtract_true = false
}
}
Quiz_VC
class Quiz_VC: UIViewController {
#IBOutlet var n1_lbl: UILabel!
#IBOutlet var back: UIButton!
#IBOutlet var next: UIButton!
#IBOutlet var enter: UIButton!
#IBOutlet var answer_field: UITextField!
#IBOutlet var symbol_lbl: UILabel!
#IBOutlet var n2_lbl: UILabel!
#IBOutlet var comment_lbl: UILabel!
#IBOutlet var score_lbl: UILabel!
var addition_true: Bool = false
var subtract_true: Bool = false
var multiply_true: Bool = false
var enter_entered_true: Bool = false
var answer: UInt32 = 0
var finalanswer: UInt32 = 0
var n1: UInt32 = 0
var n2: UInt32 = 0
var count = 0
var score = 0
var temp: UInt32 = 0
var operation: String = ""
override func viewDidLoad() {
super.viewDidLoad()
back.hidden = true
next.hidden = true
if addition_true == true {
AdditionQuestions()
}else if subtract_true == true {
SubtractionQuestions()
}
if multiply_true == true && addition_true == false && subtract_true == false{
MultiplicationQuestions()
}
}
func Operation() {
if addition_true == true {
operation = "1"
}else if subtract_true == true {
operation = "2"
}else {
operation = "3"
}
switch operation {
case "1":
finalanswer = n1 + n2
case "2":
finalanswer = n1 - n2
case "3":
finalanswer = n1 * n2
default: break
}
}
func AdditionQuestions() {
n1 = arc4random_uniform(9)+1
n2 = arc4random_uniform(9)+1
n1_lbl.text = "\(n1)"
n2_lbl.text = "\(n2)"
symbol_lbl.text = "+"
score_lbl.text = ""
comment_lbl.text = ""
}
func SubtractionQuestions() {
n1 = arc4random_uniform(9)+1
n2 = arc4random_uniform(9)+1
symbol_lbl.text = "-"
if n2 > n1 {
temp = n1
n1 = n2
n2 = temp
}
n1_lbl.text = "\(n1)"
n2_lbl.text = "\(n2)"
}
func MultiplicationQuestions() {
n1 = arc4random_uniform(9)+1
n2 = arc4random_uniform(9)+1
symbol_lbl.text = "×"
n1_lbl.text = "\(n1)"
n2_lbl.text = "\(n2)"
}
func EndQuiz() {
if count > 3 {
enter.hidden = true
next.hidden = true
back.hidden = false
score_lbl.text = "Score: \(score)"
comment_lbl.text = "Completed Quiz"
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func enter_entered(sender: AnyObject) {
if answer_field.text != nil {
enter_entered_true = true
answer = UInt32(answer_field.text!)!
count = count + 1
Operation()
if answer != finalanswer {
comment_lbl.text = "Incorrect"
} else {
comment_lbl.text = "Correct"
score = score + 1
}
} else {
comment_lbl.text = "Enter a number!"
}
enter.hidden = true
next.hidden = false
}
#IBAction func next_entered(sender: AnyObject) {
if addition_true == true {
AdditionQuestions()
comment_lbl.text = ""
}else if subtract_true == true {
SubtractionQuestions()
comment_lbl.text = ""
}
if multiply_true == true && addition_true == false && subtract_true == false{
MultiplicationQuestions()
comment_lbl.text = ""
}
enter.hidden = false
next.hidden = true
EndQuiz()
}
}
When you hit one of the buttons (Add, Subtract or Multiply) then the application immediately performs prepareForSegue before it performs the action associated with those buttons. Therefore addition_true, subtraction_true and multiplication_true are all always false and the code falls through to the else clause which sets the multiplication option.
To get around this:
In the storyboard remove the segues from the three buttons.
Add a segue from the first view controller to the second one (control drag from the yellow circle at the top of the first view controller to the body of the second view controller).
Give the segue a name(highlight the segue and name it ("mainSegue" or something) in the Attributes Inspector)
In your code add the following line to the end of each of the three actions (addition_enter, etc.):
performSegueWithIdentifier("mainSegue", sender: self)
This will ensure that the segue is called after the button actions have been performed.
In your Quiz_VC class update viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
back.hidden = true
next.hidden = true
if addition_true == true {
AdditionQuestions()
}else if subtract_true == true {
SubtractionQuestions()
}else if multiply_true == true{
MultiplicationQuestions()
}
}
and
func Operation() {
if addition_true == true {
operation = "1"
}else if subtract_true == true {
operation = "2"
}else if multiply_true == true {
operation = "3"
}
switch operation {
case "1":
finalanswer = n1 + n2
case "2":
finalanswer = n1 - n2
case "3":
finalanswer = n1 * n2
default: break
}
}
also
#IBAction func next_entered(sender: AnyObject) {
if addition_true == true {
AdditionQuestions()
comment_lbl.text = ""
}else if subtract_true == true {
SubtractionQuestions()
comment_lbl.text = ""
}else if multiply_true == true{
MultiplicationQuestions()
comment_lbl.text = ""
}else{
enter.hidden = false
next.hidden = true
EndQuiz()
}
}
I think that your #IBAction functions are not hooked up, or are not getting called because the button is linked to a segue.
This means that all of the Bools are false in prepareForSegue. And the logic in that function sets up the QuizVC for multiplication in that case (the last else clause does not have an if qualifier).
So, keep the segues in the storyboard. Populate the segue identifier string in the object inspector (the panel on the right in Xcode). Use, say, ADDITION_SEGUE, MULTIPLY_SEGUE, SUBTRACTION_SEGUE. You don't have to use caps and underscores, that's just my habit.
Then in prepareForSegue: you can tell which segue triggered the action. Set the properties on the QuizVC on the basis of that. Then you don't need those Bools at all in OptionVC.
In prepareForSegue:
if segue.identifier == "ADDITION_SEGUE" {
destinationViewController...
}
How about also putting an enum into QuizVC rather than using the Bools:
enum QuizType {
case Addition, Subtraction, Multiplication
}
That might make things a little easier in the long run. It kinda helps you manage state because the quiz type is only one of the three. Although, if the Bools work for you then fair enough.