Swift error when I press button more times than there are pizzas in my array list - swift

So I just started programming and I am now getting this error.
It occurs every time I press the button more times than there are Pizzas in the list.
Full error code: Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0):
Here`s my code so far:
import UIKit
var pizzaNumber = 0
var pizzaNames = ["Skinke Pizza", "Salat Pizza", "Pepperoni Pizza"]
let priser = [65,70,65]
var totalProdukt = pizzaNames.count
class ViewController: UIViewController {
#IBOutlet weak var produktNavn: UILabel!
#IBAction func rightButton(_ sender: UIButton) {
pizzaNumber+=1
showPizza()
}
#IBAction func leftButton(_ sender: UIButton) {
pizzaNumber-=1
if pizzaNumber < 0 {
pizzaNumber = 0
}
showPizza()
}
func showPizza() {
if pizzaNumber > totalProdukt {
pizzaNumber = pizzaNames.count
} else {
self.produktNavn.text = pizzaNames[pizzaNumber]
}
}
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.
}
}

You should make sure that pizzaNumber-1 can never be bigger than the number of elements in your array to ensure that you are never trying to access an index that doesn't exist. This can be easily done by changing totalProdukt to be a computed variable. This way, the value of the variable will always be updated when you are trying to access it.
var totalProdukt: Int {
return pizzaNames.count
}
Also bear in mind that array indexing starts at 0, so you need
if pizzaNumber >= totalProdukt {
pizzaNumber = pizzaNames.count-1
} else {
self.produktNavn.text = pizzaNames[pizzaNumber]
}
Bear in mind that with your current code, there's no need for storing the count of the array in a separate variable, since you are only using it at one place in code.
Moreover, the cleanest solution is to check the value before actually increasing it rather than when using it, this way in showPizzas you don't need to do any checks, just update the label:
class ViewController: UIViewController {
#IBOutlet weak var produktNavn: UILabel!
#IBAction func rightButton(_ sender: UIButton) {
if pizzaNumber < pizzas.count-1 {
pizzaNumber+=1
}
showPizza()
}
#IBAction func leftButton(_ sender: UIButton) {
if pizzaNumber > 0 {
pizzaNumber-=1
}
showPizza()
}
func showPizza() {
self.produktNavn.text = pizzaNames[pizzaNumber]
}
}

Here's how to fix your error
func showPizza() {
if pizzaNumber >= totalProdukt { // << Added '=' since pizzaNames[pizzaNames.count] is out of bounds
pizzaNumber = pizzaNames.count - 1
} else {
self.produktNavn.text = pizzaNames[pizzaNumber]
}
}

Related

How to random position from UIButtons has created by storyboard?[swift Xcode]

I created 12 UIButtons by storyboard, in my program, these buttons represent cards,I want to random the buttons' position for shuffling the cards.please do me a favor, give a way or idea to achieve it.
my buttons problem
import UIKit
class ViewController: UIViewController {
lazy var game = Concentration(numberOfPairsOfCards: numberOfPairOfCards) //引入model Concentration
var numberOfPairOfCards : Int {
return (cardButtons.count + 1) / 2 //read only computed properties可以省略get{}
}
var flipCount = 0 {
didSet {
flipsCountLabel.text = "Flips: \(flipCount)"
}
}
#IBOutlet var cardButtons: [UIButton]!
#IBOutlet weak var flipsCountLabel: UILabel!
#IBAction func touchCard(_ sender: UIButton) {
flipCount += 1
if let cardNumber = cardButtons.index(of: sender) {
game.chooseCard(at: cardNumber)
updateViewFromModel()
} else {
print("somthing wrong")
}
}
I have done the job.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var buttons = [UIButton]()
for index in cardButtons.indices {
buttons.append(cardButtons[index])
}
for index in cardButtons.indices {
cardButtons[index] = buttons.remove(at: buttons.count.arc4random)
}
}
You could add the buttons to an array, shuffle the array and then loop through it and place the buttons. A better solution would be to create a UICollectionView instead though.

How to set up a NSComboBox using prepare for segue or init?

I am really struggling to pass the contents of one array from a view controller to another to set up the contents of a nscombobox. I have tried everything I can think of, prepare for segue, init; but nothing seems to work.
the program flow is as follows: the user enter a number into a text field and based on it an array with the size of the number is created. Once the user presses a button the next VC appears that has a combo box and inside that combo box those numbers need to appear. All my attempts result in an empty array being passed. Could someone please take a bit of time and help me out. Im sure I'm doing a silly mistake but cannot figure out what.
Code listing below:
Class that take the user input. At this stage I'm trying to pass the contents of the array in the next class as I gave up on prepare for segue because that one crashes because of nil error. Please note that prepare for segue is uncommented in the code listing just for formatting purposes here. Im my program it is commented out as I am using perform segue at the moment.
Any solution would be nice please. Thank you.
import Cocoa
class SetNumberOfFloorsVC: NSViewController {
//MARK: - Properties
#IBOutlet internal weak var declaredNumber: NSTextField!
internal var declaredFloorsArray = [String]()
private var floorValue: Int {
get {
return Int(declaredNumber.stringValue)!
}
}
//MARK: - Actions
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction private func setNumberOfFloors(_ sender: NSButton) {
if declaredNumber.stringValue.isEmpty {
let screenAlert = NSAlert.init()
screenAlert.messageText = "Please specify the number of floors!"
screenAlert.addButton(withTitle: "Got it!")
screenAlert.runModal()
} else if floorValue == 0 || floorValue < 0 {
let screenAlert = NSAlert.init()
screenAlert.messageText = "Please input a correct number of floors!"
screenAlert.addButton(withTitle: "Got it!")
screenAlert.runModal()
} else {
for i in 0...floorValue - 1 {
declaredFloorsArray.append(String(i))
}
print("\(declaredFloorsArray)")
let declareNumberOfRoomsVC = SetNumberOfRoomsForFloorVC(boxData: declaredFloorsArray)
declareNumberOfRoomsVC.boxData = declaredFloorsArray
performSegue(withIdentifier: "set number of rooms", sender: self)
}
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if segue.identifier == "set number of rooms" {
if let addRoomsVC = segue.destinationController as? SetNumberOfRoomsForFloorVC {
addRoomsVC.floorBox.addItems(withObjectValues: declaredFloorsArray)
}
}
}
}
this is the class for the next VC with the combo box:
import Cocoa
class SetNumberOfRoomsForFloorVC: NSViewController, NSComboBoxDelegate, NSComboBoxDataSource {
//MARK: - Properties
#IBOutlet internal weak var floorBox: NSComboBox!
#IBOutlet private weak var numberOfRoomsTxtField: NSTextField!
internal var boxData = [String]()
//MARK: - Init
convenience init(boxData: [String]) {
self.init()
self.boxData = boxData
}
//MARK: - Actions
override func viewDidLoad() {
super.viewDidLoad()
floorBox.usesDataSource = true
floorBox.dataSource = self
floorBox.delegate = self
print("\(boxData)")
}
#IBAction private func setRoomsForFloor(_ sender: NSButton) {
}
//MARK: - Delegates
func numberOfItems(in comboBox: NSComboBox) -> Int {
return boxData.count
}
func comboBox(_ comboBox: NSComboBox, objectValueForItemAt index: Int) -> Any? {
return boxData[index]
}
}
First you should remove the following code.
let declareNumberOfRoomsVC = SetNumberOfRoomsForFloorVC(boxData: declaredFloorsArray)
declareNumberOfRoomsVC.boxData = declaredFloorsArray
I assume you think that the viewController you created here is passed to prepareForSegue. However the storyboard instantiates a new viewController for you.
After that you need to set your declaredFloorsArray as the the boxData of the new viewController in prepareForSegue and you should be good to go.

Why won't swift recalculate the 'if' statement?

I'm trying to create a very simple 'guessing game' where the user has to guess how many fingers the computer has up (maximum 5 fingers).
Here's the thing. When the code executes and I press submit, even when the print logs registers a correct number, the app still prints the if statement for incorrect. Where am I going wrong?
import UIKit
class ViewController: UIViewController {
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.
}
#IBOutlet weak var fingerInput: UITextField!
#IBOutlet weak var fingerResult: UILabel!
#IBAction func fingerSubmit(sender: AnyObject) {
let realNumberofFingers = Int(arc4random_uniform(6))
print(realNumberofFingers)
if fingerInput != realNumberofFingers {
fingerResult.text = "Gosh darn, that's wrong!"
} else if fingerInput == realNumberofFingers {
fingerResult.text = "Thats right!"
}
}
}
You are comparing the actual UITextField fingerInput with the realNumberofFingers. That is wrong and will always yield false. What you should do instead is parse the string from the fingerInput and check if the integer contained in that string is equal to realNumberofFingers:
#IBAction func fingerSubmit(sender: AnyObject) {
let input = Int(fingerInput.text!)
if let enteredFingers = input {
let realNumberofFingers = Int(arc4random_uniform(6))
print(realNumberofFingers)
if enteredFingers == realNumberofFingers {
fingerResult.text = "Thats right!"
} else {
fingerResult.text = "Gosh darn, that's wrong!"
}
} else {
fingerResult.text = "Please enter a correct guess - an integer!"
}
}

Uncaught exception of type NSException

I'm beginning to teach myself Swift, I am truly a beginner and I am working on a calculator app just as an intro project. I keep getting a thread error and it is terminating with an uncaught exception of type NSException. I've read in several places that this is usually caused by a missing or wrong connection from the storyboard to the view controller but I triple checked all of my connections and I don't think that is the problem. Here is my code for the view controller, is there an issue with it? I followed a tutorial for the most part.
import UIKit
extension String{
var doubleValue: Double{
if let number = NSNumberFormatter().numberFromString(self) {
return number.doubleValue
}
return 0
}
}
class ViewController: UIViewController {
var isTypingNumber = false
var firstNumber:Double? = 0
var secondNumber:Double? = 0
var operation = ""
#IBOutlet var calculatorDisplay: UILabel!
#IBAction func numberTapped(sender: AnyObject) {
var number = sender.currentTitle
if isTypingNumber {
calculatorDisplay.text = calculatorDisplay.text! + number!!
} else{
calculatorDisplay.text = number
isTypingNumber = true
}
}
#IBAction func calculationTapped(sender: AnyObject) {
isTypingNumber = false
firstNumber = calculatorDisplay.text!.doubleValue
operation = sender.currentTitle!!
}
#IBAction func equalsTapped(sender: AnyObject) {
isTypingNumber = false
var result = 0.0
secondNumber = calculatorDisplay.text!.doubleValue
if operation == "+"{
result = firstNumber! + secondNumber!
} else if operation == "-"{
result = firstNumber! - secondNumber!
} else if operation == "*"{
result = firstNumber! * secondNumber!
}
else if operation == "/"{
result = firstNumber! / secondNumber!
}
calculatorDisplay.text = "\(result)"
}
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.
}
}
I really appreciate any help I can get!
Did you happen to change the name of any IBOutlet or IBAction since first installing it into the Storyboard/xib?
Try going to your viewcontroller in Interface Builder, right-click the VC object to see all connected outlets, and check that everything's hooked up and that there aren't any dead links. (i.e. if you renamed func equalsTapped() to func equalsTapped(sender: AnyObject), the exception will be raised because equalsTapped no longer exists, instead equalsTapped: now does, and the connection is to the first.)

swift unable to access contents of variable in IBAction. error: "Expected declaration"

This program compiles fine with no errors, but crashes when i click the Button attached to IBAction check Answer.
in applicationWillResignActive(_:) i see "Thread 1: signal SIGABRT"
and in my debug area, i see:
'NSInvalidArgumentException', reason: '-[Fingerz.ViewController checkAnswerButton:]: unrecognized selector sent to instance 0x7f89e254a180'
Can someone point me in the right direction towards what I am missing?
import UIKit
var num = 0
class ViewController: UIViewController
{
#IBAction func fingerGenerator(sender: AnyObject) //request random number
{
var randomNum = Int(arc4random_uniform(6))
num = randomNum
}
#IBOutlet weak var userGuess: UITextField! //user enters Guess here
#IBOutlet weak var userResult: UILabel! //display if user is right or wrong
#IBAction func checkAnswer(sender: AnyObject)
{
var userInput = userGuess.text.toInt()
println(userInput)
if num == userInput
{
userResult.text = "Great Job"
}
else
{
userResult.text = "Try again"
}
}
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.
}
}
The code you posted needs a closing bracket to close the class.
import UIKit
// You requested it to make this variable a global variable
var num = 0
class ViewController: UIViewController {
#IBAction func fingerGenerator(sendor: AnyObject)
{
var randomNum = Int(arc4random_uniform(6))
num = randomNum
println(num)
}
}