NSButton state not changing - swift

The following code works perfect in my sandbox:
#IBAction func filterClicked(sender: NSButton) {
println(sender.state)
if let clickEvent = NSApp.currentEvent! {
if Int(clickEvent.modifierFlags.rawValue) & Int(NSEventModifierFlags.ControlKeyMask.rawValue) != 0 {
if sender.state == NSOffState {
sender.state == NSOnState
}
}
}
println(sender.state)
}
The connected button is an On-Off button. So when it's on and I ctrl-click it it will stay on.
Unfortunately in my app where I really need this it does not work. I checked that in both sandbox and prod app the bindings/settings are identically for both buttons. The debugger shows that
sender.state == NSOnState
is simply not performed. state stays NSOffState. Gnawing my keyboard did not help. Any idea?

You are not assign any value to the button state.
sender.state = NSOnState
Update for Swift 4.2
sender.state = NSControl.StateValue.on

Changing state of a Radio Button (Check state) for swift 4:
#IBOutlet weak var checkedButton: NSButton!
checkedButton.state = NSControl.StateValue.off // State = off
checkedButton.state = NSControl.StateValue.on // State = on

I know this already has an accepted answer, but sharing my scenario in case it trips up someone else:
I had the same issue where I couldn't programmatically set the state for my button in a custom table view cell. MY issue, is that I was trying to set the state when my table first created the cell. Instead, I had to make sure to override the layout method in my custom cell and set the state there.

I had this in a CollectionViewItem...
I had an outlet for the favouriteButton...
class PictureCollectionViewItem: XCollectionViewItem
{
#IBOutlet var thumbnailView: NSImageView!
#IBOutlet var tagsView: NSTextField!
#IBOutlet var favouriteButton: NSButton!
...
}
I had linked the outlet to the Collection View Item object
but NOT linked it to the File's Owner...
As soon as I linked it to the File's Owner as well, ... it all worked.

Related

I want to Switch UIView by Clicking UISegmented Control but my Code is not working

i want to Switch UIView by clicking Segmented Control but this Code is not working.
#IBOutlet weak var flightTypeSegCont: UISegmentedControl!
#IBAction func flightType(_ sender: UISegmentedControl) {
if(flightTypeSegCont.selectedSegmentIndex == 0)
{
self.direcrCard.isHidden = false
self.ViaCardView.isHidden = true
}
else
{
self.direcrCard.isHidden = true
self.ViaCardView.isHidden = false
}
}
Did you check if the function is getting called in XCode debugger? If not, connect IBAction from storyboard / xib to your function - valuechanged callout of UISegmentedControl.
If it is being called but views are not hidden as you want, check if they are having parent/child relationship. To check this in more details, go to XCode->View Debugging->Capture View hierarchy option to see the runtime UIView layout.

Can I change outlets using an array, instead of hard coding everything?

I have an app where a user can select a number of different buttons onscreen. When a user selects a button, it turns green and the text will be used in a later view. I am trying to make everything nice and swift by minimising the amount of code I am writing.
Every button is connected to the same action and their identity is determined by their tag. What I have done is created 2 arrays to track the card name and their on/off state. When a card is pressed the cardPressed function is called, this decides whether to turn the card green or white currently (it will do more later).
What I want to do is to perform the colour change in one line of code, instead of
cardOne.backgroundColor = UIColor.white
I want to do this [#1]
cardList[cardNumber].backgroundColor = UIColor.green
so that my outlet changes depending on the selection made. I would normally just have a massive switch statement that would read like so
switch cardList[cardNumber] {
case 0:
cardOne.backgroundColor = UIColor.green
case 1:
cardTwo.backgroundColor = UIColor.green
case 2:
cardThree.backgroundColor = UIColor.green
case So on so forth:
cardInfinity.......
default:
break
}
Obviously when I try to do [#1] I get an error because it is a string, not an outlet connection. What I would like to know, is there anyway to trick xcode into recognising it as an outlet, or better yet have a way to change the outlets I am acting upon in one line of code?
Hopefully I haven't rambled too much and you can understand my thought process! I have included all of the relevant code below, obviously it won't compile. If you have any ideas they would be appreciated, or if I'm being too optimistic and this isnt possible, just let me know :) for now I will be using a big switch statement! (maybe this is useful to me in the future!)
Thanks!
private let cardList = ["cardOne","cardTwo","cardThree"]
private var cardState = [false, false, false]
//Card functions
private func selectCard(cardNumber: Int){
cardState[cardNumber] = true
cardList[cardNumber].backgroundColor = UIColor.green
}
private func deselectCard(cardNumber: Int){
cardState[cardNumber] = false
//cardOne.backgroundColor = UIColor.white
}
//Decide which function to perform, based on the card information recieved
private func cardPressed(cardNumber: Int){
let selectedCardName = cardList[cardNumber]
let selectedCardState = cardState[cardNumber]
print("\(selectedCardName)")
print("\(selectedCardState)")
switch selectedCardState {
case true:
deselectCard(cardNumber: cardNumber)
case false:
selectCard(cardNumber: cardNumber)
}
}
//UI Connections
//Card button actions
#IBAction func buttonPressed(_ sender: UIButton) {
//Determine which button has been pressed
//let cardName = sender.currentTitle!
let cardSelection = sender.tag - 1
cardPressed(cardNumber: cardSelection)
}
//Card button outlets
#IBOutlet weak var cardOne: UIButton!
#IBOutlet weak var cardTwo: UIButton!
The solution lies in the wonderful world of object-oriented programming. Instead of using parallel arrays, you can create your own data type to group this data and behavior together.
If you created your own UIButton subclass, you could keep track of whether the button is selected with your own custom property, and make visual modifications as needed.
class CardButton: UIButton {
var isChosen: Bool = false {
didSet { backgroundColor = isChosen ? UIColor.green : UIColor.white }
}
}
If you set the buttons in the storyboard to be your new CardButton type, you can use their isChosen property in code.
Your buttonPressed function could look like this instead:
#IBAction func buttonPressed(_ sender: CardButton) {
sender.isChosen = !sender.isChosen
}
This would allow you to remove the majority of your existing code, since the data is stored inside each of your buttons.

Image change dependent of UISlider value

I have some images that need to be displayed dependent on the value of a slider. It is not working - where am I going wrong?
#IBOutlet weak var image1: UISlider! [this is connected to the slider NOT the image]
image1.setImage(UIImage(named:"image1.png"),forState:UIControlState.Selected)
#IBAction func sliderValue(sender: UIButton) {
let slider value = Int(sender.value)
if sliderValue == 1 {
image1.setImage
}
}
Maybe you want to do something like that ? You check the value of your slider each time its value change, then you set an image to your imageView.
#IBOutlet weak var imageView: UIImageView!
#IBAction func sliderValueChanged(sender: UISlider) {
var sliderValue = Int(sender.value)
if sliderValue == 1 {
self.imageView.image = UIImage(named: "foo")
}
}
To connect your Slider in your storyboard to your code :
In the right panel of your storyboard, select your ViewController, go to the third tab. In Custom Class > Class field, enter class you are using. It should autocomplete.
Click on "SHOW THE ASSISTANT EDITOR" (two circles icon) to split your window between your storyboard and your code.
Press Ctrl + drag the element (here your slider) to the code.
Choose Outlet or Action. For your imageView, choose outlet, because you will be able to interact with it programmatically, but the user won't do any action with it. I'll let you search Google if you need more details on IBOutlet and IBAction
Credits : Images from this site

Hide button function if statement issue - Swift

I have a function to hide a slider if another button is pressed. I currently have:
#IBOutlet weak var sliderHide: UISlider!
#IBAction func sliderHide(sender: UISlider) {
if (buttonPlay.selected) {
sliderHide.hidden = false
}
else if (!buttonPlay.selected) {
sliderHide.hidden = true
}
}
The build is running but the slider only hides if itself is selected. It does nothing if the button is selected.
Use == not = when comparing,= is an assignment operator.
Moreover, if buttonImage is not a variable representing the control state of a button, but the button itself you want to do:
if buttonImage.selected == false {
}
However, you should use an #IBAction for the button if you want to run a function when it is pressed.
Please consider using an #IBAction for this kind of thing unless your button is programmatically created. You can read more about it here:
http://rshankar.com/different-ways-to-connect-ibaction-to-uibutton/
I
I think you want
add an Outlet to the slider like the picture and then wherever you play the sound, make the sliderYouMightHide.hidden = false and wherever the sound stops make the sliderYouMightHide.hidden = true. You might also want to make it hidden in viewDidLoad

Disable a Button

I want to disable a button (UIButton) on iOS after it is clicked. I am new to developing for iOS but I think the equivalent code on objective - C is this:
button.enabled = NO;
But I couldn't do that on swift.
The boolean value for NO in Swift is false.
button.isEnabled = false
should do it.
Here is the Swift documentation for UIControl's isEnabled property.
If you want the button to stay static without the "pressed" appearance:
// Swift 2
editButton.userInteractionEnabled = false
// Swift 3
editButton.isUserInteractionEnabled = false
Remember:
1) Your IBOutlet is --> #IBOutlet weak var editButton: UIButton!
2) Code above goes in viewWillAppear
The way I do this is as follows:
#IBAction func pressButton(sender: AnyObject) {
var disableMyButton = sender as? UIButton
disableMyButton.enabled = false
}
The IBAction is connected to your button in the storyboard.
If you have your button setup as an Outlet:
#IBOutlet weak var myButton: UIButton!
Then you can access the enabled properties by using the . notation on the button name:
myButton.enabled = false
Disable a button on Swift 3:
yourButton.isEnabled = false
For those who Googled "disable a button" but may have more nuanced use cases:
Disable with visual effect: As others have said, this will prevent the button from being pressed and the system will automatically make it look disabled:
yourButton.isEnabled = false
Disable without visual effect: Are you using a button in a case where it should look normal but not behave likes button by reacting to touches? Try this!
yourButton.userInteractionEnabled = false
Hide without disabling: This approach hides the button without disabling it (invisible but can still be tapped):
yourButton.alpha = 0.0
Remove: This will remove the view entirely:
yourButton.removeFromSuperView()
Tap something behind a button: Have two buttons stacked and you want the top button to temporarily act like it's not there? If you won't need the top button again, remove it. If you will need it again, try condensing its height or width to 0!
Swift 5 / SwiftUI
Nowadays it's done like this.
Button(action: action) {
Text(buttonLabel)
}
.disabled(!isEnabled)
You can enable/disable a button using isEnabled or isUserInteractionEnabled property.
The difference between two is :
isEnabled is a property of UIControl (super class of UIButton) and it has visual effects (i.e. grayed out) of enable/disable
isUserInteractionEnabled is a property of UIView (super class of UIControl) and has no visual effect although but achieves the purpose
Usage :
myButton.isEnabled = false // Recommended approach
myButton.isUserInteractionEnabled = false // Alternative approach
Let's say in Swift 4 you have a button set up for a segue as an IBAction like this #IBAction func nextLevel(_ sender: UIButton) {}
and you have other actions occurring within your app (i.e. a timer, gamePlay, etc.). Rather than disabling the segue button, you might want to give your user the option to use that segue while the other actions are still occurring and WITHOUT CRASHING THE APP. Here's how:
var appMode = 0
#IBAction func mySegue(_ sender: UIButton) {
if appMode == 1 { // avoid crash if button pressed during other app actions and/or conditions
let conflictingAction = sender as UIButton
conflictingAction.isEnabled = false
}
}
Please note that you will likely have other conditions within if appMode == 0 and/or if appMode == 1 that will still occur and NOT conflict with the mySegue button. Thus, AVOIDING A CRASH.
The button can be Disabled in Swift 4 by the code
#IBAction func yourButtonMethodname(sender: UIButon) {
yourButton.isEnabled = false
}
in order for this to work:
yourButton.isEnabled = false
you need to create an outlet in addition to your UI button.
Building on other answers here. I wanted to disable button for a few seconds to prevent double taps. Swift 5 version, xcode 13.4.1 likes this and has no warnings or errors.
#IBAction func saveComponent(_ sender: Any) {
let myButton = sender as? UIButton
myButton?.isEnabled = false
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(2000))
{
myButton?.isEnabled = true
}
}