Can we make 1 UIButton for 2 action with swift? - ios

i want to make 2 action for a button like that.
selected and deselected action for 1 button.
#IBAction func btntouch(sender: UIButton) {
if firsttouch
{
print bla bla
change button to selected style. maybe background color.
}
else
{
}
}
how can i do that?

In case you need to split two button statuses - like ON and OFF, try this:
var buttonSwitched : Bool = false
#IBAction func btntouch(sender: UIButton) {
//this line toggle your button status variable
//if true, it goes to false, and vice versa
self.buttonSwitched = !self.buttonSwitched
if self.buttonSwitched
{
//your UI styling
}
else
{
//your opposite UI styling
}
}

Create 2 IBActions:
#IBAction func touchDown(_ sender: AnyObject) {
print("down")
}
#IBAction func touchUp(_ sender: AnyObject) {
print("up")
}
When connecting the first one, make sure the event is set to touchDown. For the second one, make sure it is set to touchUpInside

Yes, you can. Depending on your requirements, you could store the current state of the button in the view controller or in the model.
If the visual change caused by the first touch needs to be persisted across opening and closing of your view controller, store the value indicating the change in the model; if you need to reset the visuals when the view controller shows, store the value in the view controller itself:
var firstTouch = true
#IBAction func btntouch(sender: UIButton) {
if firstTouch {
firstTouch = false
...
} else {
...
}
}

Related

Different functions for one bar button item

I have a view controller with a segmented control(only two segments: Songs and Playlists) and a bar button item. When the songs segment is selected, I want the bar button item to perform action1, and when the playlists segment is selected, I want the bar button item to perform action2.
In an attempt to do this I created this function which I declared in the viewDidLoad and in the viewDidAppear:
func settearButton() {
let indice = segmentFiltroMusica.selectedSegmentIndex
switch indice {
case 0: //Canciones
btnAgregarMusica.action = #selector(irAAgregarCancionesVC)
btnAgregarMusica.target = self
case 1: // Playlists
btnAgregarMusica.action = #selector(irAAgregarPlaylistsVC)
btnAgregarMusica.target = self
default: print("")
}
}
However, the bar button item is only performing action1, no matter what segment is selected. How could I fix this?
I don't think you actually want to change the action of the button. Handle the button tap, check the state of your segment control, then call the appropriate method.
func settearButton() {
let index = segmentFiltroMusica.selectedSegmentIndex
switch index {
case 0:
irAagregarCancionesVC()
case 1:
irAggregarPlaylistsVC()
default:
break
}
}
First you should put your function in the class and not the viewDidLoad() or viewDidAppear(). You can make it private since you seem to use it only localy.
If you are using storyboards with a ViewController you probably know that you can drag actions and outlets of your segment and button onto your viewController Class.
Here is how I would do this, by using a Boolean value and change this to select between my actions:
private var myChoice: Bool = false
#IBOutlet weak var segment: NSSegmentedControl!
#IBAction func segmentAction(_ sender: Any) {
let index: Int = self.segment.selectedSegment
switch index {
case 0:
myChoice = true
case 1:
myChoice = false
default:
fatalError("This segment does not exist!")
}
}
#IBAction func buttonAction(_ sender: Any) {
if myChoice {
// Do case one
} else {
// Do case two
}
}
If you have more elements in the segment to choose from, take an enum instead of the Boolean. I kept your switch which is good if you will add an enum later, else you can just replace the content of the segmentAction() with:
myChoice = self.segment.selectedSegment == 0

Why are animated calls of UIView.isHidden = false compounded?

As you can see I'm having trouble formulating the question. Let me try to explain:
I'm using a search bar in my swift ios app. In order to get a desired animation effect I put it in a vertical stack view and then animate its isHidden property. This way search bar pushes down other children of the stack view as it animates in or pulls them up as it animates out. So far so good.
I've noticed a behavior that I think is strange. Could be a bug or could be me not understanding how things work. Basically if I call search bar hiding method x times in a row I need to call search bar showing method x times before it would show. I'd expect to have to make just one call to show search bar regardless of how many times I called hiding method. The issue doesn't exist other way around: if I call search bar showing code x times I only need to call hiding method once for it to go away. This doesn't happen if I set isHidden without animating it...
Here's a sample code and a video of the issue. I'd appreciate it if someone would help me understand this behavior.
class ViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar! {
didSet {
searchBar.isHidden = true
}
}
#IBAction func showAction(_ sender: UIButton) {
expandSearch()
}
#IBAction func hideAction(_ sender: UIButton) {
collapseSearch()
}
private func expandSearch() {
UIView.animate(withDuration: 0.3){
self.searchBar.isHidden = false
}
}
private func collapseSearch() {
UIView.animate(withDuration: 0.3){
self.searchBar.isHidden = true
}
searchBar.resignFirstResponder()
}
}
You should not call an asynchronous animation of searchbar x times, instead of I suggest you to keep its state in variable, something like isSearchBarHidden,
and check it before show/hide search bar. You could use just one method with such signature showSearchBar(show: Bool) and setting this variable there.
#IBAction func showAction(_ sender: UIButton) {
showSearchBar(true)
}
#IBAction func hideAction(_ sender: UIButton) {
showSearchBar(false)
}
private
func showSearchBar(_ show: Bool) {
guard isSearchBarHidden != show else {
return
}
UIView.animate(withDuration: 0.3, animations: {
self.searchBar.isHidden = show
}) {
self.isSearchBarHidden = show
if !show && searchBar.isFerstResponder {
searchBar.resignFirstResponder
}
}
}
private
var isSearchBarHidden: Bool = true
Also it is a good practice to check if your textView/textField/searchBar isFirstResponder before call resignFirstResponder.
Hope it will help. Good luck!

programmatically toggle UISwitch, prevent IBAction function

I have a UISwitch, when it is toggled, the IBAction is triggered:
#IBAction func mySwitchToggled( switch_: UISwitch ) {
...
}
So, when user toggle the switch, the above function is invoked.
At some point, I also need to toggle the switch programmatically:
mySwitch.setOn(false, animated: false) //It triggers the IBAction function
The above code triggers the IBAction function.
For my special requirement, I need to have the IBAction function being triggered when user toggled the switch but when programmatically toggle the switch, I don't want the IBAction function get triggered.
How to programmatically toggle my switch without triggering the IBAction function?
hmmm... intersting. It gets triggered in my project
I don't have enough rep to comment so I post it as a answer going at PPL his answer, did you checked your outlets. Most of the time the storyboard keeps the connection to your other IB action which causing them to trigger both. (removing existing outlets and implementing the value change, should work)
Here is another (some what hacky) solution, by implementing a skip boolean when calling the switch by code:
var skip: Bool = false
#IBAction func mySwitchToggled( switch_: UISwitch ) {
guard !skip else {
skip = false
return
}
// do stuff
}
func someFunc() {
// called it like this
skip = true
mySwitch.setOn(false, animated: false)
}
Please find below, Here swcValueChanged is Value Changed function and it will call only when user toggle the switch.
#IBAction func swcValueChanged(_ sender: Any) {
print("Switch value changed")
}
Here on button tap event, above function will not call.
#IBAction func btnTapped(_ sender: Any) {
swcTemp.setOn(!swcTemp.isOn, animated: true)
}

How to disable UISlider?

I've seen answers about this but no actual code explaining how to, I'm new to swift so really confused on how to perform this simple task.
I have a UISlider However I want to disable the sliders function when an if statement is true.
I current have a UISlider with an if statement but can't workout how to disable it.
#IBAction func radiusSlider(sender: UISlider) {
if location == false {
//Disable Slider
} else {
radiusData.radiusValue = Double(sender.value)
radiusLabel.text = "Radius: \(sender.value)km"
NSNotificationCenter.defaultCenter().postNotificationName(radiusValue, object: self)
}
}
Or would this be in within the viewDidLoad? If so how?
Set the UISlider's enabled property to false.
#IBAction func radiusSlider(sender: UISlider) {
if location == false {
sender.enabled = false
} else {
radiusData.radiusValue = Double(sender.value)
radiusLabel.text = "Radius: \(sender.value)km"
NSNotificationCenter.defaultCenter().postNotificationName(radiusValue, object: self)
}
}
If you want to enable/disable your slider in other functions of your view controller, you will need to make an IBOutlet property for your slider.

One UIbutton can be chosen at a time

I have three buttons,and only one button can be chosen by the user at a time,that means that other then the initial state where none are chosen only one button can be at a highlighted state at a time.After another button (a forth one) is clicked,all the previous button's abilities to be clicked on are disabled.How do I do this?
button.enabled = false /// this will make a button disabled in swift
Why not use the 4th button to toggle a bool - that can be used to check on the state of the other buttons?
var lockedButtons: Bool = true
#IBAction func toggleButtonLock(sender: UIButton) {
lockedButtons = !lockedButtons
}
#IBAction func Button1(sender: UIButton) {
if !lockedButtons{
//Button1 code
}
}
//button 2 & 3 code similar....

Resources