Array of UIButtons or method UIButton(named: "\(string)") - ios

Is it possible to make an array of UIButtons?
let buttonArray: [UIButton] = [UIButton(Button1)!, UIButton(Button2)!, UIButton(Button3)!]
To reference later as
buttonArray[0].setImage(UIImage, forState: UIControlState.Normal)
Or somehow set a
var button = UIButton.whoseName = "Specific String"
button.setImage(UIImage, forState: UIControlState.Normal)
VC1:
import UIKit
class VC1: UIViewController {
#IBOutlet weak var Card1: UIButton!
#IBOutlet weak var Card2: UIButton!
#IBOutlet weak var Card3: UIButton!
let Cards: [UIImage] = [UIImage(named: "Default")!, UIImage(named: "2s")!,UIImage(named: "2h")!,UIImage(named: "2c")!,UIImage(named: "2d")!,]
// var CardCaller: Array<UIButton> = [Card1, Card2, Card3]
let CardCallers: [UIButton] = [Card1, Card2, Card3] //ERROR: 'VC1.Type' does not have a member named 'Card1'
var caller = ""
var Index2 = Int()
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.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let KVC = segue.destinationViewController as VC2
KVC.source = segue.identifier!
}
#IBAction func unwind(unwindSegue: UIStoryboardSegue){
//Card1.setImage(Cards[Index2], forState: UIControlState.Normal)
//let button = UIButton(named: "Card1")!
if caller == "Card1" {Card1.setImage(Cards[Index2], forState: UIControlState.Normal)} else if caller == "Card2" {Card2.setImage(Cards[Index2], forState: UIControlState.Normal)} else if caller == "Card3" {Card3.setImage(Cards[Index2], forState: UIControlState.Normal)}
}
#IBAction func text(sender: AnyObject) {
println(caller)
println(Index2)
}
}
The IBOutlets are wired properly to Storyboard buttons; I created them with control/drag to the view controller.

This shouldn't be a problem, but it may have something to do with when you're accessing the buttons. Try creating the array globally and adding the buttons to it once they've loaded:
class VC1: UIViewController {
#IBOutlet weak var Card1: UIButton!
#IBOutlet weak var Card2: UIButton!
#IBOutlet weak var Card3: UIButton!
var CardCallers: [UIButton] = [UIButton]() // Empty UIButton array
override func viewDidLoad() {
self.CardCallers = [self.Card1, self.Card2, self.Card3] // Buttons have now loaded in the view
}
}

You can.
Two ways to do it:
var buttonsArray: Array<UIButton> = [button1, button2]
Or
#IBOutlet var buttonsArray: Array<UIButton> = []
For the later one, it can be filled from the storyboard as an IBOutletCollection
Please note that views can be assigned to an IBOutlet and an IBOutletCollection at the same time.

Related

UIImageView Array iOS13

I am trying with learning Swift and got stuck on an issue here.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var diceImageView1: UIImageView!
#IBOutlet weak var diceImageView2: UIImageView!
var leftDiceNumber=1
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
diceImageView1.image = UIImage(imageLiteralResourceName: "DiceSix")
// change transparency with diceImageView1.alpha=0.7
}
#IBAction func rollButtonPressed(_ sender: UIButton) {
print("button pressed")
diceImageView1 = [ UIImageView(imageLiteralResourceName: "DiceOne"),UIImageView(imageLiteralResourceName: "DiceTwo"),UIImageView(imageLiteralResourceName: "DiceThree"),UIImageView(imageLiteralResourceName: "DiceFour"),UIImageView(imageLiteralResourceName: "DiceFive"),UIImageView(imageLiteralResourceName: "DiceSix")],[leftDiceNumber]
leftDiceNumber=leftDiceNumber+1
}
}
But all I get is the error messages on the IBAction:
1.Argument passed to call that takes no arguments
2.Cannot assign value of type '[UIImageView]' to type 'UIImageView'
3.Consecutive statements on a line must be separated by ';'
4.Expected expression
What's the difference between UIImageView and UIImage ? When they should be used?
Many Thanks in advance !
You want to change the .image property to change the image.
To "cycle through" the dice, you could do this:
class DiceViewController: UIViewController {
#IBOutlet weak var diceImageView1: UIImageView!
#IBOutlet weak var diceImageView2: UIImageView!
let diceNames: [String] = [
"DiceOne", "DiceTwo", "DiceThree", "DiceFour", "DiceFive", "DiceSix"
]
var leftDiceNumber = 0
override func viewDidLoad() {
super.viewDidLoad()
diceImageView1.image = UIImage(named: diceNames[leftDiceNumber % 6])
}
#IBAction func rollButtonPressed(_ sender: UIButton) {
print("button pressed")
// increment the index
leftDiceNumber += 1
// udpate the image view
diceImageView1.image = UIImage(named: diceNames[leftDiceNumber % 6])
}
}
I'm guessing your goal is to "randomly roll" the dice, so take a look at this slightly different class:
class DiceViewController: UIViewController {
#IBOutlet weak var diceImageView1: UIImageView!
#IBOutlet weak var diceImageView2: UIImageView!
let diceNames: [String] = [
"DiceOne", "DiceTwo", "DiceThree", "DiceFour", "DiceFive", "DiceSix"
]
override func viewDidLoad() {
super.viewDidLoad()
// start with both dice at One
diceImageView1.image = UIImage(named: diceNames[0])
diceImageView2.image = UIImage(named: diceNames[0])
}
#IBAction func rollButtonPressed(_ sender: UIButton) {
print("button pressed")
// arrays are Zero-based, so get a random Int
// from 0 to 5
//let l = Int.random(in: 0...5)
//let r = Int.random(in: 0...5)
//diceImageView1.image = UIImage(named: diceNames[l])
//diceImageView2.image = UIImage(named: diceNames[r])
// more "modern Swifty" method
if let nm = diceNames.randomElement() {
diceImageView1.image = UIImage(named: nm)
}
if let nm = diceNames.randomElement() {
diceImageView2.image = UIImage(named: nm)
}
}
}

UIButton linked with IBAction will not work in simulation on physical device nor simulator in Xcode 9.2

I added the UIButton with Control + Drag, added the variables and arc4random for randomized numbers, and then used a front function to test my button to make sure it worked. But the button is totally unresponsive and I have no errors in my code.
import UIKit
class ViewController: UIViewController {
var randomDiceIndex1 : Int = 0
var randomDiceIndex2 : Int = 0
#IBOutlet weak var diceImageView1: UIImageView!
#IBOutlet weak var diceImageView2: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func rollButtonPressed(_ sender: UIButton) {
randomDiceIndex1 = Int(arc4random_uniform(6))
randomDiceIndex2 = Int(arc4random_uniform(6))
print(randomDiceIndex1) //This line of code is what I used to test
}
}
Assign action programmatically.
yrBtnOutlet.addTarget(self, action: #selector(self. rollButtonPressed(_:)), for: .touchUpInside)
Hope this will help.

Programmatically change slider value and update the Label

I have 3 sliders as shown above:
And when the "Min tip" it's equal or greater than "Default tip", I add 1 to "Default tip". And the same logic it's for Default to Max tip.
So, until now I have this code, that works partially because the Default tip's slider grows in the UI, but the label isn't updated because the delegate isn't called.
#IBOutlet weak var minLabel: UILabel!
#IBOutlet weak var defaultLabel: UILabel!
#IBOutlet weak var maxLabel: UILabel!
#IBOutlet weak var minSlider: UISlider!
#IBOutlet weak var defaultSlider: UISlider!
#IBOutlet weak var maxSlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
minSlider.addTarget(self, action: #selector(SettingsViewController.minSliderValueChanged(_:)), forControlEvents: UIControlEvents.AllEvents)
defaultSlider.addTarget(self, action: #selector(SettingsViewController.defaultSliderValueChanged(_:)), forControlEvents: UIControlEvents.AllEvents)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func minSliderValueChanged(sender: UISlider) {
let valueMin = Int(minSlider.value)
let valueDefault = Int(defaultSlider.value)
_ = Int(maxSlider.value)
minLabel.text = "Min tip: \(valueMin)%"
if(valueMin >= valueDefault){
defaultSlider.value = Float(valueMin+1)
}
}
#IBAction func defaultSliderValueChanged(sender: UISlider) {
let value = Int(defaultSlider.value)
defaultLabel.text = "Default tip: \(value)%"
}
#IBAction func maxSliderValueChanged(sender: UISlider) {
let value = Int(maxSlider.value)
maxLabel.text = "Max tip: \(value)%"
}
What I'm missing?
After defaultSlider.value = Float(valueMin+1) update the text of the label, like so:
defaultLabel.text = "Default tip: \(valueMin+1)%"
Slider values range from 0 (slider at left end) to 1 (slider at right end).
By doing let valueMin = Int(minSlider.value), variable valueMin can either be 0, or 1. I assume this isn't what you want really.
Perhaps this is closer to what you're looking for?
#IBAction func minSliderValueChanged(sender: UISlider) {
let valueMin = minSlider.value
let valueDefault = defaultSlider.value
_ = Int(maxSlider.value)
minLabel.text = "Min tip: \(Int(valueMin*100))%"
if(valueMin >= valueDefault){
defaultSlider.value = valueMin
}
}

Swift: How a Button Can Perform a Sequence

How can a button unhid textfields each time its pressed and then after 4 times of being pressed the button becomes inactive? Here is my code so far. Thanks in advance!
import UIKit
class AddNewGameViewController: UIViewController {
#IBOutlet weak var Player1: UITextField!
#IBOutlet weak var Player2: UITextField!
#IBOutlet weak var Player3: UITextField!
#IBOutlet weak var Player4: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
Player1.hidden = true
Player2.hidden = true
Player3.hidden = true
Player4.hidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addPlayer(sender: UIButton) {
sender.enabled = false
Player1.hidden = false
Player2.hidden = false
Player3.hidden = false
Player4.hidden = false
}
change your #IBOutlets to a #IBOutlet Collectionlike this :
#IBOutlet var players: [UITextField]!
then connect each textfield to it Player1->Player2-> Player3->Player4
finally in the btn action :
for textField in players {
if textField.hidden {
textField.hidden = false
if textField == players.last {
sender.enabled = false
}
break
}
}
update
you can hide all them with players.forEach {$0.hidden = true} in viewDidload
or hide them in xib/storyboard.
connect image :

How can I change UIStepper value when changed from UITextField?

I'm very new to all of this and I found some code that got me understanding some of this syntax. I'm trying to create a textfield that lets me type in a value that updates the stepper's value. The stepper currently works (updates the uitextfield) but when I change the value in the textfield it doesn't update the stepper's value, so when I click on the stepper, it reverts back to whatever value it was before I typed in a value... Can anyone tell me why the two functions STracksValueDidChange and CTrackValueDidChange have errors?
Here's my code so far:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var STracks: UITextField!
#IBOutlet weak var STracksStepper: UIStepper!
#IBOutlet weak var CTracks: UITextField!
#IBOutlet weak var CTrackStepper: UIStepper!
override func viewDidLoad() {
super.viewDidLoad()
STracksStepper.autorepeat = true
STracksStepper.maximumValue = 100.0
STracksStepper.minimumValue = 2.0
STracksStepper.stepValue = 2.0
print(STracksStepper.value)
STracks.text = "\(Int(STracksStepper.value))"
STracksStepper.addTarget(self, action: "SstepperValueDidChange:", forControlEvents: .ValueChanged)
STracks.addTarget(self, action: "STextValueDidChange:", forControlEvents: .ValueChanged)
CTrackStepper.autorepeat = true
CTrackStepper.maximumValue = 100.0
CTrackStepper.minimumValue = 2.0
CTrackStepper.stepValue = 2.0
print(CTrackStepper.value)
CTracks.text = "\(Int(CTrackStepper.value))"
CTrackStepper.addTarget(self, action: "CstepperValueDidChange:", forControlEvents: .ValueChanged)
CTracks.addTarget(self, action: "CTextValueDidChange:", forControlEvents: .ValueChanged)
}
//Steppers will update UITextFields
func SstepperValueDidChange(stepper: UIStepper) {
let stepperMapping: [UIStepper: UITextField] = [STracksStepper: STracks]
stepperMapping[stepper]!.text = "\(Int(stepper.value))"
}
func STracksValueDidChange(SText: UITextField) {
let STextMapping: [UITextField: UIStepper] = [STracks: STracksStepper]
STextMapping[SText]!.value = "(SText.text)"
}
func CstepperValueDidChange(stepper: UIStepper) {
let stepperMapping: [UIStepper: UITextField] = [CTrackStepper: CTracks]
stepperMapping[stepper]!.text = "\(Int(stepper.value))"
}
func CTrackValueDidChange(CText: UITextField) {
let CTextMapping: [UITextField: UIStepper] = [CTracks: CTrackStepper]
CTextMapping[CText]!.value = "(CText.text)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Try something like this.
CTrackStepper.value = Double(Textfield.text)
I am not so sure what the mapping is in your code.
But i don't think you need it for changing the value.
Update, made a project my self:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textfield: UITextField!
#IBOutlet weak var stepper: UIStepper!
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.
}
#IBAction func stepperValueChanged(sender: UIStepper) {
textfield.text = String(sender.value)
}
#IBAction func valueChanged(sender: UITextField) {
if Double(sender.text!) != nil {
stepper.value = Double(sender.text!)!
}
}
}
For steppervaluechanged and valuechanged just drag from uistepper and textfield and choose action and change the Anyobject to Uistepper of Uitextfield.
Good luck :)

Resources