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
}
}
Related
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()
So I am quite new to coding, learning Swift 3 on Udemy. I'm trying to test my skills by building a music app that contains 3 sound files, at the moment I am struggling to get the image of the current song that should be playing once my UIButton is pressed. I have created an array containing the image files but for some reason it only shows 2 out of the 3 images and will not go further nor will it let me loop the images, any and all suggestions are welcome.
I have tried a for-in loop which is not what I want at the moment. I am trying to get the function to update songImage to accept my array and link to the sender.tag property to cycle through the images
class ViewController: UIViewController {
// Instance Variables
var playTheSong : AVAudioPlayer!
var imageArray = ["songImage1", "songImage2", "songImage3"]
var allSongNamesAndDescriptions = MusicClassBank()
var nextImage = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
albumArtwork.image = UIImage(named: "songImage3")
}
#IBAction func buttonPressed(_ sender: UIButton) {
updateSongImage(selectedImageFile: imageArray[sender.tag - 1])
nextImage = nextImage + 1
}
#IBOutlet weak var albumArtwork: UIImageView!
#IBOutlet weak var nameOfSong: UILabel!
#IBOutlet weak var songDescription: UILabel!
// Cycle through images upon button being pressed.
func updateSongImage(selectedImageFile : String) {
if nextImage <= 3 {
albumArtwork.image = UIImage(named: selectedImageFile)
}
else {
nextImage = 0
}
}
Right now the code is showing just the image displayed upon view load and the next image in the array. I cannot get it to go through the entire array and keep going when the button is pressed.
You are using the "next" UIButton sender.tag as a parameter to change the image, but that tag never changes. So:
In your viewDidLoad() method, you show the third image
When you press the "next" button, you update the image to 1 (probably the sender.tag is 1)
Pressing the button again don't update the image
You can try something like this:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//Set the first image
updateSongImage(selectedImageFile : imageArray[0])
}
#IBAction func buttonPressed(_ sender: UIButton) {
//If nextImage is less than imageArray.count - 1 (because arrays start with 0), add one to nextImage. Else, nextImage return to zero
nextImage = nextImage < imageArray.count - 1 ? nextImage + 1 : 0
updateSongImage(selectedImageFile: imageArray[nextImage])
}
func updateSongImage(selectedImageFile : String) {
//Here we only need to update the image, because the if is outside
albumArtwork.image = UIImage(named: selectedImageFile)
}
I have two IBAction groups with three buttons each.
Each button has a different tag - within each group: 1, 2 and 3.
I have three arrays, with three values each.
I want to press the first button of the first IBAction and change the title of the three buttons in the second IBAction, based on the group of arrays.
Here is the code:
import UIKit
class ViewController: UIViewController {
var firstArray = ["A1","A2","A3"]
var secondArray = ["B1","B2","B3"]
var thirdArray = ["C1","C2","C3"]
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func greenButtons(_ sender: UIButton) {
if sender.tag == 1 {
//change the title of the grayButtons with the firstArray
}
if sender.tag == 2 {
//change the title of the grayButtons with the secondArray
}
if sender.tag == 3 {
//change the title of the grayButtons with the thirdArray
}
}
#IBAction func grayButtons(_ sender: UIButton) {
}
}
You can try
// create outlet group for each
#IBOutlet weak var greenButtons:[UIButton]!
#IBOutlet weak var grayButtons:[UIButton]!
Inside action of greenButtons
grayButtons.forEach { $0.setTitle(firstArray[$0.tag - 1],for:.normal) }
Instead of if check you can construct the array as
let allArr = [ ["A1","A2","A3"], ["B1","B2","B3"],["C1","C2","C3"]]
Then
grayButtons.forEach { $0.setTitle(allArr[sender.tag - 1][$0.tag - 1],for:.normal) }
I have password UITextfield that is currently turned on as secure entry. I would like to show the user the password he has typed inform of text again in the UITextfield when the UISwitch is turned on. Here is my implementation that so far. It works when i print it out in the console but doesn't in the UITextfield. I would like to show it on once the UISwitch is turned on and off when the UISwitch is turned off.
#IBOutlet weak var existingPasswordTexfField: UITextField!
#IBOutlet weak var newPasswordTextField: UITextField!
#IBOutlet weak var changePasswordSwitch: UISwitch!
#IBAction func showPassword(_ sender: UISwitch) {
if changePasswordSwitch.isOn {
guard let oldText = existingPasswordTexfField.text else { return }
if existingPasswordTexfField.isSecureTextEntry {
existingPasswordTexfField.text = oldText
} else {
print("Pawword is already secure")
}
}
}
According to Apple Doc ìsSecureTextEntry is a writable property
So you in your showPassword IBAction you need to set it toggle it at some point :
existingPasswordTexfField.isSecureTextEntry = false
or just
existingPasswordTexfField.isSecureTextEntry = !changePasswordSwitch.isOn
You'll need to change the isSecureTextEntry flag on the textfield when the user flips the switch.
#IBAction func showPassword(_ sender: UISwitch) {
existingPasswordTextField.isSecureTextEntry = changePasswordSwitch.isOn
}
This is also works
existingPasswordTexfField.isSecureTextEntry = changePasswordSwitch.isOn ? false : true
I have a textfield that I would like the user to be able to enter numbers for a array in. Ideally the button would save the number, then clear the textfield for another number to be enter. This would be a process that would just go in a loop. So its just save the number, clear the number, repeat infinitely.
import UIKit
class ViewController: UIViewController {
#IBOutlet var enterText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func submitText(_ sender: Any) {
}}
Lets define and array.
var arrayOfInt = [Int]()
Suppose you have button action method and textField Object (could be IB outlet) to which user enters number.
#IBAction func submitText(_ sender: Any) {
if let text = textField.text {
if let number = Int(text){
arrayOfInt.append(number)
}else {
print("Please enter number")
}
}
}