How can I not repeat the array when I click on the button in swift? I'm trying to generate fruits without them repeating. Can I sort the string that way it runs through all the fruits one by one? It doesn't have to be randomized. I just want each word to show only once when I click the button and show the last array "There aren't any fruit options left"
I tried to randomize the string but that repeats the fruits. I just want it to go one by one. When I press the button on my screen the output on the image label should give me each fruit one at a time.
ie. Button pressed"
Output: "Apple"
button pressed again
Output: "Banana"
and so on until the last string shows "There aren't any fruit options left"
import UIKit
class fruitrandomViewController: UIViewController {
#IBOutlet weak var nextfruitButton: UIButton!
#IBOutlet weak var fruitbox: UILabel!
#IBAction func fruitbutton(_ sender: UIButton) {
let array = ["Apple","Banana","Orange","Pinapple", "Plum", "Pear","T"There aren't any fruit options left",]
let randomFruitgenerator = Int(arc4random_uniform(UInt32(array.count)))
fruitbox.text = array[randomFruitgenerator]
}
}
You need to somehow keep track of the array elements that you have already used. You could do this in a couple of ways:
Keep an index property that tracks the next element of the array
Mutate the array itself as elements are consumed
Either way, you should make the array an instance property, not a local variable in the function itself.
Here is an example of the second approach (I prefer this since I think it makes the code a little simpler, as you don't need to track the next index).
class fruitrandomViewController: UIViewController {
#IBOutlet weak var nextfruitButton: UIButton!
#IBOutlet weak var fruitbox: UILabel!
var fruit = ["Apple","Banana","Orange","Pinapple", "Plum", "Pear",].shuffled()
#IBAction func fruitbutton(_ sender: UIButton) {
if fruit.isEmpty {
fruitbox.text = "There's no more fruit left"
} else {
fruitbox.text = self.fruit[0]
self.fruit.remove(at:0)
}
}
}
For completeness, here is the first approach (with an added "previous fruit" button):
class fruitrandomViewController: UIViewController {
#IBOutlet weak var nextfruitButton: UIButton!
#IBOutlet weak var fruitbox: UILabel!
let fruit = ["Apple","Banana","Orange","Pinapple", "Plum", "Pear",].shuffled()
var nextFruit = 0
#IBAction func fruitbutton(_ sender: UIButton) {
if nextFruit < fruit.count {
fruitbox.text = self.fruit[nextFruit]
nextFruit += 1
} else {
fruitbox.text = "There's no more fruit left"
}
}
#IBAction func previousFruitButton(_ sender: UIButton) {
guard nextFruit > 0 else {
return
}
nextFruit -= 1
fruitbox.text = self.fruit[nextFruit]
}
}
If you don't want the fruit in a random order, just remove the .shuffled()
Related
So I am working on a BlackJack game for iOS using Swift. I have two buttons, HIT and STAY. Here is where my problem lies: When I press the originally, it is player 1's turn. But after clicking the HIT button, I want the turn label to oscillate between player 2 and player 1. So after player 1 clicks HIT button, I want the turn label to read player 2 and then player 1. Here is what I got so far:
class ViewController: UIViewController {
var deck = PlayingCardDeck()
#IBOutlet weak var cardLabel: UILabel!
#IBOutlet weak var playerTurn: UILabel!
#IBOutlet weak var scorePlayerOne: UILabel!
#IBOutlet weak var scorePlayerTwo: UILabel!
#IBAction func btnHit(_ sender: Any) {
cardLabel.text = String(describing: deck.drawCard()!)
playerTurn.text = String(describing: "Player 2")
}
#IBAction func btnStay(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
deck.shuffle()
}
}
With the method I have, it mimics what I want to happen (switches to player 2)
You need a variable to track which player is currently playing and then change the label based on those variable value.
var isFirstPlayerTurn: Bool = true
#IBAction func btnHit(_ sender: Any) {
cardLabel.text = String(describing: deck.drawCard()!)
isFirstPlayerTurn = !isFirstPlayerTurn
playerTurn.text = isFirstPlayerTurn ? "Player 1" : "Player 2"
}
Create two labels, one for each player. Then hide player 2's label and flip it while hidden in viewDidLoad(). Once the turn changes, flip both labels while simultaneously showing and hiding the labels based who's turn it is.
To flip the label, use CGAffineTransform. Use the labels' alpha property to show and hide the labels.
func changeTurn(_ player: Int) {
UIView.animate(withDuration: 0.5) {
playerTurn1.transform = CGAffineTransform(scaleX: -playerTurn1.transform.a, y: playerTurn1.transform.d)
playerTurn2.transform = CGAffineTransform(scaleX: -playerTurn2.transform.a, y: playerTurn2.transform.d)
playerTurn1.alpha = player == 1 ? 1 : 0
playerTurn2.alpha = player == 2 ? 1 : 0
}
}
Usage:
#IBOutlet weak var playerTurn1: UILabel!
#IBOutlet weak var playerTurn2: UILabel!
private var turn = 1
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
deck.shuffle()
playerTurn2.alpha = 0
playerTurn2.transform = CGAffineTransform(scaleX: -playerTurn2.transform.a, y: playerTurn2.transform.d)
}
#IBAction func btnHit(_ sender: Any) {
cardLabel.text = String(describing: deck.drawCard()!)
turn = turn == 1 ? 2 : 1
changeTurn(turn)
}
Make sure both labels are the same frames.
I am recreating a simple app that is a paramedic case logger, effectively it is a bunch of buttons or textfields that get their .text value time stamped and pasted into a UItextView field to create a chronological list of action to refer back to when a paramedic writes up their patient notes.
I have created a tab bar controlled app using the Xcode template.
I have created the UIbuttons and UItextfields that create and paste the string into a test UItextview on the same field.
I have created a func that creates the time stamp string
I run into trouble getting the same string to show on the UItextview on the 2nd view.
RESEARCH
As I am only new to this I have read lots of posts on here with user defaults, segues, delegates/protocols and cannot seem to effectively implement these in my specific circumstance (still not super sure I understand those enough yet to do it).
I have got the point that I have saved the string into a user.default value and then I can use that value in the 2nd view with a func to insert the text and clear the user.default value but I cannot seem to get the function to run from the first view? (get the encounter nil value error).
I feel like this should be a pretty simple process, so not getting it to function is very frustrating...
QUESTION
So I was hoping someone might be able to demo the simple way to take a UItextField.text input from FirstViewController and then when a UIbutton is pressed on FirstViewController pass the string to SecondViewController and insert it into a UITextView field (I don't want to display the 2nd view).
From this demo I'm hoping I can reverse engineer a solution into my code as a learning opportunity without just having my exact code handed to me on a silver platter.
import UIKit
class FirstViewController: UIViewController, UITextFieldDelegate {
// View OUTLETS
#IBOutlet weak var customNoteField: UITextField!
#IBOutlet weak var reportTextViewFieldTemp: UITextView!
#IBOutlet weak var lastEntryTV: UITextView!
#IBOutlet weak var caseIDTF: UITextField!
// Class VARIABLES
let timeButtonArray = ["blank0", "Call Received1", "Dispatched2", "Enroute3", "On Scene4", "At Patient5", "Depart Scene6", "At Hospital7", "Available8",]
// VIEW DID LOAD STUFF
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
self.customNoteField.delegate = self
}
//TIMING BUTTON PRESSED
#IBAction func timeButtonPressed(_ sender: UIButton) {
//GATHER DATA
let timingButtonInput = timeButtonArray[sender.tag]
let DTGstamp = dateTimeStamp()
//FORM STRING
let buttonData = ("\(DTGstamp) \(timingButtonInput) \n")
//SEND buttonDATA TO ReportViewController
/*??? The part I need help with*/
}
//CUSTOM ENTRY UITextfield PRESSED
#IBAction func customNoteDone(_ sender: Any) {
//GATHER DATA
let DTGstamp = dateTimeStamp()
let customNote = customNoteField.text
//FORM STRING
let customData = ("\(DTGstamp) \(customNote) \n")
//TEST FOR EMPTY TEXT
if customNote != "" {
//SEND customDATA TO ReportViewController
/*??? The part I need help with*/
}
//FUNCTION TO GENERATE DATE,TIME GROUP AS CONSTANT
func dateTimeStamp() -> String {
var date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "ddLLLyy HH:mm:ss"
print (dateFormatter.string(from: date))
return (dateFormatter.string(from: date))
}
}
//
// ReportViewController.swift
// EMS Case Logger
//
// Created by Allan Ravenscroft on 3/3/19.
// Copyright © 2019 Allan Ravenscroft. All rights reserved.
//
import UIKit
class ReportViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var reportTextViewField: UITextView!
#IBOutlet weak var reportEmailButton: UIButton!
#IBOutlet weak var reportEditButton: UIButton!
#IBOutlet weak var reportClearButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
hideKeyboardWhenTappedAround()
reportEditButton.layer.cornerRadius = reportEditButton.frame.height / 2
reportEmailButton.layer.cornerRadius = reportEmailButton.frame.height / 2
reportClearButton.layer.cornerRadius = reportClearButton.frame.height / 2
}
//Actions when the clear button is pressed
#IBAction func clearButtonPressed(_ sender: Any) {
reportTextViewField.text = ""
}
//Actions when the edit button is pressed
#IBAction func editButtonPressed(_ sender: Any) {
}
//Actions when the email button is pressed
#IBAction func emailButtonPressed(_ sender: Any) {
showMailComposer(bodytext: reportTextViewField.text)
}
}
I know this is not a demo, but maybe can help you
Make a new NSObject file
inside the class put a new variable
import UIKit
class test: NSObject {
var a:String = ""
}
at your ViewController declare a new var referencing the class
let testVar = test()
in your customNote checker
test.a = customNote
then at your 2nd ViewController, do the same thing
let testVar = test()
testVar.a //this is your customNote String
hope this helps
Im developing in Swift and I am displaying one string from an array by clicking a button. However, after the array is empty and the last string of the array is displayed, I want the user to be unable to click on the button since there are no more strings to display and the array is empty. So far I have crafted code to where the button is disabled after the array is empty but it stays disabled even after I had more strings to the array (by clicking another button). Any help would be highly appreciated.
#IBOutlet weak var selectedChoice: UILabel!
#IBOutlet weak var field: UITextField!
var choices = [String]()
//first button that adds string to array
#IBAction func addToChoices(_ sender: Any) {
choices.append(field.text!)
print(choices)
print(choices.count)
}
//button that I want to disable once 'choices.isEmpty' but enable it again after more strings are added to 'choices'
#IBAction func shuffleTilExhuasted(_ sender: Any) {
let button = sender as? UIButton
let rand = Int(arc4random_uniform(UInt32(choices.count)))
selectedChoice.text = choices[rand]
choices.remove(at: rand)
switch choices.isEmpty {
case true:
button?.isEnabled = false
case false:
button?.isEnabled = true
}
Re enable it when add , create IBOutlet of the button
//first button that adds string to array
#IBAction func addToChoices(_ sender: Any) {
choices.append(field.text!)
self.btn.isEnabled = true
print(choices)
print(choices.count)
}
OR use didSet with the array
var choices:[String] = []
{
didSet {
self.btn.isEnabled = choices.isEmpty
}
}
I am trying to control drop two UILabels onto a UIViewController. I keep receiving Cannot override strong property with weak property error.
Here is a short excerpt from my code. Here is a screenshot of all the errors https://gyazo.com/bd97fa42443d12a3aa17a2de55f78b60
import UIKit
class ViewController: UIViewController {
#IBOutlet private weak var display: UILabel!
#IBOutlet private weak var description: UILabel!
private var userIsInTheMiddleOfTyping = false
#IBAction private func touchDigit(_ sender: UIButton) {
let digit = sender.currentTitle!
if (digit == "c") {
display.text = " "
} else {
print("touchDigit \(digit) digit")
if userIsInTheMiddleOfTyping {
let textCurrentlyInDisplay = display.text
if (sender.currentTitle!) == "c" {
print("it printed c")
display.text = "sam"
You need to rename your description variable since description is the name of a method inherited from NSObject (the base class of UIViewController).
You should declare your UILabels with optional type UILabel? instead UILabel!
So I'm trying to create a simple function in my app in which a button adds 1 integer to the label when it's pressed and the other one clears it.
Here is the code:
class ViewController: UIViewController {
var number = 0
#IBOutlet weak var tapCount: UILabel!
#IBAction func plusTapped(sender: AnyObject) {
number = number + 1
tapCount.text = String(number)
}
#IBAction func minusTapped(sender: AnyObject) {
var totalNumber = number - number
tapCount.text = String(totalNumber)
}
However the label does clear when the minus button is tapped but when the plus button is tapped after, it adds up from the previous number before the minus button was pressed.
How do I fix this in a way so that it actually clears the label?
#IBAction func minusTapped(sender: AnyObject) {
number = 0 // add this line to reset the counter, the real number
tapCount.text = String(number)
}
Try
#IBAction func minusTapped(sender: AnyObject) {
number = 0
tapCount.text = String(0)
}
I think it's because when you're handling tap on minus you are altering local variable and not changing number itself. You should change "number" too. Se my comments in your's code
class ViewController: UIViewController {
var number = 0
#IBOutlet weak var tapCount: UILabel!
#IBAction func plusTapped(sender: AnyObject) {
number = number + 1
tapCount.text = String(number)
}
#IBAction func minusTapped(sender: AnyObject) {
//here totalNumber is changed but number is still the same
var totalNumber = number - number
tapCount.text = String(totalNumber)
}