For some reason, even if input a valid input, namely, an integer, it does seem to go into if statement in the function, #IBAction func guess(sender: UIButton){}. In other words, if I input 5, the console output will say "Please input a valid number." Not "you guessed to high" or "you guessed to low" or "you win!". Any suggestion on how to fix this?
The following is my code:
class ViewController: UIViewController {
//just some member variables. I don't think the problem is here.
#IBOutlet weak var inputField: UITextField!
#IBOutlet weak var output: UITextView!
var guesses : UInt = 0;
var number : UInt32 = 0;
var gameover = false;
let MAX_GUESSES = 8;
var possibleGuess : Int?
override func viewDidLoad() {
super.viewDidLoad()
number = generateNewNumber()
consoleOut("I'm thinking of a number...\n")
var possibleGuess : Int? = inputField.text.toInt()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//consoleOut here prints out stuff on the app.
func consoleOut(text : String) {
output.text = output.text + text;
}
func generateNewNumber() -> UInt32 {
return arc4random_uniform(100) + 1
}
func clearInput() {
output.text = ""
}
//here lies the problem. The control never seems to go inside of
//if let guess = possibleGuess{}
#IBAction func guess(sender: UIButton) {
if let guess = possibleGuess {
if UInt32(guess) > number {
consoleOut("\(guess): You guessed to high\n")
++guesses
}
else if UInt32(guess) < number {
consoleOut("\(guess): You guessed to low\n")
++guesses
}
else {
consoleOut("\(guess): You win!\n")
consoleOut("Go again? (y/n)")
guesses = 0
gameover = true
}
clearInput()
}
else {
clearInput()
consoleOut("Please input a valid number")
}
}
}
This is a very common mistake.
You declare a variable possibleGuess as optional Int instance variable, but later you declare a variable with the same name in viewDidLoad() whose scope is locally only within the viewDidLoad() method.
Solution : delete the var keyword in the viewDidLoad() method.
possibleGuess = inputField.text.toInt()
The explicit type annotation is not needed too as the type has been already defined.
Related
I have two Random numbers generating in ViewDidLoad. I Want to plus these two numbers and the result should be checked in a button with data of a input field. my problem is that I do not know how to transfer result to the function CheckResultBtn . now it does not recognise result.
here is My codes and I really appreciate any kinds of help
class ViewController: UIViewController {
#IBOutlet weak var lblRandomNumOne: UILabel!
#IBOutlet weak var lblRandomNumTwo: UILabel!
#IBOutlet weak var KidsField: UITextField!
#IBOutlet weak var Showresult: UILabel!
#IBOutlet weak var CheckResult: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let x = Int.random(in: 0 ..< 10)
lblRandomNumOne.text = String(x);
let y = Int.random(in: 0 ..< 10)
lblRandomNumTwo.text = String(y);
let result = x + y;
CheckResultBtn(result) //not sure about this
}
#IBAction func CheckResultBtn(_ sender: Any)
{
if (KidsField != nil)
{
let kidsresult = Int(KidsField.text!) ;
if (result == kidsresult)
{
Showresult.text = "Bravo";
}
else
{
Showresult.text = "Try Again!"
}
}
}
}
declare the variable "result" before the viewDidload function
var result : Int!
then proceed to perform the operation on the variable in your viewDidload and you can get rid of this line
CheckResultBtn(result)
and you should be able to access the result variable in your IBAction function
You can try
#IBAction func checkResultBtn(_ sender: Any) {
displayRes(Int(kidsField.text!)!)
}
func displayRes(_ result:Int) {
showresult.text = result == kidsresult ? "Bravo" : "Try Again!"
}
Then inside viewDidLoad
displayRes(x+y)
create a new function instead of using action Method
like this :
func CheckResultBtn(_ result : Int) {
if (KidsField != nil)
{
let kidsresult = Int(KidsField.text!) ;
if (result == kidsresult)
{
Showresult.text = "Bravo";
}
else
{
Showresult.text = "Try Again!"
}
}
}
or create a variable
var result : Int?
assign a value
result = x + y;
and use inside the action Method
var result : Int?
override func viewDidLoad() {
super.viewDidLoad()
let x = Int.random(in: 0 ..< 10)
lblRandomNumOne.text = String(x);
let y = Int.random(in: 0 ..< 10)
lblRandomNumTwo.text = String(y);
result = x + y;
}
#IBAction func CheckResultBtn(_ sender: Any) {
if (KidsField != nil)
{
let kidsresult = Int(KidsField.text!) ;
if (result == kidsresult)
{
Showresult.text = "Bravo";
}
else
{
Showresult.text = "Try Again!"
}
}
}
I have a problem, Xcode gives me this error "EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode==0*0)" while I'm trying to make my buttons delete indexes in my array, "shoppingList".
Please help me and tell me what i did wrong so i can improve later on.
//
// ViewController.swift
// ShoppingList
//
// Created by Petr Chrastek on 29/03/16.
// Copyright © 2016 ACS. All rights reserved.
//
class ViewController: UIViewController {
#IBOutlet weak var labelText: UILabel!
#IBOutlet weak var label0: UILabel!
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
var shoppingList = ["eggs", "milk", "cake", "sugar"]
#IBAction func remove0(sender: UIButton) {
shoppingList.removeAtIndex(0)
}
#IBAction func remove1(sender: UIButton) {
shoppingList.removeAtIndex(1)
}
#IBAction func remove2(sender: UIButton) {
shoppingList.removeAtIndex(2)
}
#IBAction func remove3(sender: UIButton) {
shoppingList.removeAtIndex(3)
}
override func viewDidLoad() {
super.viewDidLoad()
let str: String? = shoppingList[0]
let str1: String? = shoppingList[1]
let str2: String? = shoppingList[2]
let str3: String? = shoppingList[3]
let count = shoppingList.count
labelText.text? = "you are missing \(count) items"
if str != nil {
label0.text? = "\(str)"
} else {
label0.text? = "empty"
}
if str1 != nil {
label1.text? = "\(str1)"
} else {
label1.text? = "empty"
}
if str2 != nil {
label2.text? = "\(str2)"
} else {
label2.text? = "empty"
}
if str3 != nil {
label3.text? = "\(str3)"
} else {
label3.text? = "empty"
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
After you delete the first item from your list, shoppingList will only have 3 items in it, so accessing shoppingList[3] will crash (remember with 3 items only 0..<2 are valid.
The easiest way to resolve the problem is to use the following pattern so you're checking the count to make sure indices are valid before using them.
if shoppingList.count > 0 {
label0.text = shoppingList[0]
} else {
label0.text = "empty"
}
if shoppingList.count > 1 {
label1.text = shopingList[1]
} else {
label1.text = "empty"
}
I've made some additional changes as well, such as not pointless using string interpolation to turn a String into the same String, since [String][n] will always return a String (never a String?) there's no need to deal with the Optionals
You'll have similar problems (in fact, probably what you're running into now) when you try to:
shoppingList.removeAtIndex(3)
the second time, since 3 is no longer a valid index, instead, use:
if shoppingList.count > 3 {
shoppingList.removeAtIndex(3)
}
The main objective of this code is the ability for a user to highlight/favourite a page in application. I have an array of quotes which is scrolled through by the user on button click. I would like to have it so that when a "favourite" button is clicked (not implemented in code yet). The current element which the user is viewing is extracted (The whole string?) and then somehow marked / sent into another array. This array is then displayed using my own method. I don't know how this could be done. Here's my viewcontroller file.
import UIKit
class DreamViewController: UIViewController {
#IBOutlet var QuoteImage: UIImageView!
#IBOutlet weak var DreamLabel: UILabel!
var counter = 1
var factIndex = 0
let dreamFact = Dream()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
DreamLabel.text = dreamFact.dreamArray[factIndex]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func LeftSwipe() {
factIndex--
var number = dreamFact.dreamArray.count - 1
if (factIndex < 0){
self.factIndex = number
}
DreamLabel.text = dreamFact.dreamArray[factIndex]
if counter == 1 {
counter = 36
} else {
self.counter--
}
QuoteImage.image = UIImage(named: "frame\(counter).jpg")
}
#IBAction func RightSwipe() {
factIndex++
if factIndex >= dreamFact.dreamArray.count {
self.factIndex = 0
}
DreamLabel.text = dreamFact.dreamArray[factIndex]
if counter == 36 {
counter = 1
} else {
self.counter++
}
QuoteImage.image = UIImage(named: "frame\(counter).jpg")
}
}
if any additional information is required please let me now as soon as possible. Thank You!
You can use the factIndex, that you're using to track the current index, to remove the particular "quote" from the dreamArray that the user has favourited. Seeing as the factIndex is correct in tracking the current quote the user is viewing we know that we can use this to extract the right object from the array.
The suggestion below presumes that you create an Array to store your favourite quotes, such as...
var favouriteQuotesArray: [String] = []
func makeQuoteFavourite() {
let currentQuote = dreamFact.dreamArray[factIndex]
favouriteQuotesArray.append(currentQuote)
}
Getting the error of Immutable value of type '[String]' only has mutating member in my swift project and researched some answers and none seem to fix the problem in my context. Take A Look:
import UIKit
class PassionViewController: UIViewController {
var factIndex = 0
var counter = 1
#IBOutlet var QuoteImage: UIImageView!
#IBOutlet weak var funFactLabel: UILabel!
let factBook = FactBook()
let Liked = Favourite()
override func viewDidLoad() {
super.viewDidLoad()
funFactLabel.text = factBook.factsArray[factIndex]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func showFunFact() {
factIndex++
if (factIndex >= factBook.factsArray.count) {
self.factIndex = 0
}
funFactLabel.text = factBook.factsArray[factIndex]
if counter == 36 {
counter = 1
} else {
self.counter++
}
QuoteImage.image = UIImage(named: "frame\(counter).jpg")
}
#IBAction func goBack() {
factIndex--
var number = factBook.factsArray.count-1
if (factIndex < 0){
self.factIndex = number
}
funFactLabel.text = factBook.factsArray[factIndex]
if counter == 1 {
counter = 36
} else {
self.counter--
}
QuoteImage.image = UIImage(named: "frame\(counter).jpg")
}
#IBAction func Like() {
let currentQuote = factBook.factsArray[factIndex]
Liked.favouriteArray.append(currentQuote)
}
}
The let currentQuote = factBook.factsArray[factIndex], factBook.factsArray is retrieved from another view controller which is a array collection. Liked.favouriteArray.append(currentQuote) is to store this element into favouriteArray which is from a struct called Favourite:
import Foundation
struct Favourite {
var favouriteArray:[String] = []
}
However, the line Liked.favouriteArray.append(currentQuote) is generating the error: Immutable value of type '[String]' only has mutating member. How can I resolve this error?
It's unclear because you didn't provide the Favourite type, but I assume it's either a struct, or it's a class that includes factsArray as a let variable. In either case, you're trying to modify a let variable, which is not allowed (mutating an immutable value). Either liked or factsArray must be var. (If Favourite is a struct, then liked must be var in either case.)
Note that Swift functions, methods, properties, and variables should start with a lowercase letter. Leading uppercase letters denote types.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var yourScore: UITextField!
#IBOutlet weak var totalScore: UITextField!
#IBOutlet weak var labelText: UILabel!
#IBAction func buttonPressed(sender: AnyObject) {
let score1: Int = yourScore.text.toInt()!
let score2: Int = totalScore.text.toInt()!
let mistakes = score2 - score1
let scoreFinal = ((((score2 / 2) - mistakes)*23)/score2)+75
labelText.text = "\(scoreFinal)"
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Something is wrong with my code. Is it because of data types or something? When I load the application, it just opens fine but when the button is pressed, the app crashes.
http://i.stack.imgur.com/B2i5Z.png
You could safely unwrap the values with if let:
if let score1 = yourScore.text.toInt() {
if let score2 = totalScore.text.toInt() {
let mistakes = score2 - score1
let scoreFinal = ((((score2 / 2) - mistakes)*23)/score2)+75
labelText.text = "\(scoreFinal)"
} else {
// no valid score2
}
} else {
// no valid score1
}
While unwrapping, you can't just willy nilly use the values. Before unwrapping you have to check if the current value is nil. If it's not nil, then you can safely unwrap the text.