How to pass a UIView on UIButton as a parameter on click event - swift

I generated a multiple UIButton and UIView using loop, the problem is, I want that generated UIView to be hidden when the generated UIButton was clicked,
The question is, how can I pass the UIView on a UIButton click event so that the system knows what UIView will going to be hidden
This is my code that generate UIButtons and UIViews
for (key, value) in myStringsArray {
let myButton = UIButton()
let myView = UIView()
panelButton.tag = value
panelButton.addTarget(self, action: #selector(onMyButtonClick), for: .touchUpInside)
}
The only data that I can pass on .tag was Int
And this is my onMyButtonClick function that listen on click event of the UIButton
#objc func onMyButtonClick (sender: UIButton) {
print(sender.tag)
}
What I want to do is to have a click listener function that is working like this
func clickMe (view: UIView, isOpen: Bool) {
view.isHidden = isOpen
}

You can assign the button and the view the same tag.
then you can find the view by tag and hide it.
#objc func onMyButtonClick (sender: UIButton) {
print(sender.tag)
if let foundView = view.viewWithTag(sender.tag) {
foundView.isHidden = true
}
}

Related

appearance().setBackgroundImage Not Working On Custom Class

I have created a UIBarButtonItem custom class and assigned one bar button item with this class in the storyboard.
In the app delegate I'm trying to set the appearance for it using:
VIPButton.appearance().setBackgroundImage(UIImage(named: "vipButton"), for: .normal, barMetrics: .default)
However while this works for regular UIBarButtonItems it has no affect for my custom class bar button item.
Any help would be appreciated.
create custom class from UIButton:
public class SimpleButton: UIButton {
#objc dynamic var backColor: UIColor? {
didSet {
self.backgroundColor = self.backColor
}
}
#objc dynamic var image: UIImage? {
didSet {
self.setImage(self.image, for: .normal)
}
}
}
Next you create a class from UIBarButtomItem.
now set customView property to SimpleButon for custom Appearance and set action for this like below:
public class SimpleBarButton: UIBarButtonItem {
// create object from simpleButton
private let button = SimpleButton()
public required init?(coder: NSCoder) {
super.init(coder: coder)
// add target for button
self.button.addTarget(self, action: #selector(self.buttonTapped(_:)), for: .touchUpInside)
// set title
self.button.setTitle("title", for: .normal)
self.button.sizeToFit()
// assing simple button to customView property
self.customView = self.button
}
// get callback from touchUp button
#objc func buttonTapped(_ sender: UIButton) {
// here set callback for tapped on BarButtonItem
// check target and action is not Nil
guard let target = self.target, let action = self.action else {
return
}
// call selector (implement to your ViewController)
// pass self for parameters
target.performSelector(inBackground: action, with: self)
}
}
I created a class in this section and assigned a button to the customView variable.
Now I add style to SimpleButton like this:
SimpleButton.appearance().backColor = .red
SimpleButton.appearance().image = UIImage.init(named: "images")!
now for create BarButtonItem on storyboard and change custom class to SimpleBarButton:
now create ViewController and add action for event barButton:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sampleClicked(_ sender: SimpleBarButton) {
print("callBack from action on BarButton Item")
}
}
and assign this function to BarButton:
UI output:

how to add pan gesture on long pressing a button [duplicate]

I want to trigger two action on button click and button long click. I have add a UIbutton in my interface builder. How can i trigger two action using IBAction can somebody tell me how to archive this ?
this is the code i have used for a button click
#IBAction func buttonPressed (sender: UIButton) {
....
}
can i use this method or do i have to use another method for long click ?
If you want to perform any action with single tap you and long press the you can add gestures into button this way:
#IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, #selector (tap)) //Tap function will call when user tap on button
let longGesture = UILongPressGestureRecognizer(target: self, #selector(long)) //Long function will call when user long press on button.
tapGesture.numberOfTapsRequired = 1
btn.addGestureRecognizer(tapGesture)
btn.addGestureRecognizer(longGesture)
}
#objc func tap() {
print("Tap happend")
}
#objc func long() {
print("Long press")
}
This way you can add multiple method for single button and you just need Outlet for that button for that..
#IBOutlet weak var countButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
addLongPressGesture()
}
#IBAction func countAction(_ sender: UIButton) {
print("Single Tap")
}
#objc func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
}
}
func addLongPressGesture(){
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gesture:)))
longPress.minimumPressDuration = 1.5
self.countButton.addGestureRecognizer(longPress)
}
Why not create a custom UIButton class, create a protocol and let the button send back the info to delegte. Something like this:
//create your button using a factory (it'll be easier of course)
//For example you could have a variable in the custom class to have a unique identifier, or just use the tag property)
func createButtonWithInfo(buttonInfo: [String: Any]) -> CustomUIButton {
let button = UIButton(type: .custom)
button.tapDelegate = self
/*
Add gesture recognizers to the button as well as any other info in the buttonInfo
*/
return button
}
func buttonDelegateReceivedTapGestureRecognizerFrom(button: CustomUIButton){
//Whatever you want to do
}

Swift 3 Method from Class not working with #selector syntax

I feel as though I'm not understanding the Swift #selectors properly. I'm trying to connect a button to a method from another class.
I have a class to print the button when pushed:
class printThings {
#IBAction func printMe(_ sender: UIButton){
print("Button Pushed.")
}
}
And then the ViewController:
class ViewController : UIViewController {
override func ViewDidLoad(){
super.viewDidLoad()
//button setup here
let printMe = printThings()
button.addTarget(printMe, action: #selector(printMe.printMe(_:)), for: .touchUpInside)
//add button to subview
}
}
This never triggers the print statement in the class. I'm sure I'm missing something simple.
Thanks.
The problem is that printMe is a temporary, local variable:
let printMe = printThings() // local variable
button.addTarget(printMe, action: #selector(printMe.printMe(_:)), for: .touchUpInside)
// ... and then viewDidLoad ends, and `printMe` vanishes
So by the time you push the button, printMe has vanished; there is no one to send the button message to.
If you want this to work, you need to make printMe persist:
class ViewController : UIViewController {
let printMe = printThings() // now it's a _property_ and will persist
override func viewDidLoad(){
super.viewDidLoad()
//button setup here
button.addTarget(self.printMe, action: #selector(self.printMe.printMe(_:)), for: .touchUpInside)
//add button to subview
}
}

How to highlight the background of a UIButton when it is clicked and "unhighlight" it?

I am trying to create 4 UIButtons that highlight and stay highlighted when they are clicked. The only problem is I need only one UIButton to be Highlighted at a time. So, if there is a UIButton highlighted already, I need it to be "unhighlighted" and highlight the UIButton I clicked. I have tried to do this before and failed. Please help me with this problem.
I am using the Swift coding language to do this.
Any input or suggestions would be greatly appreciated.
If you give this answer an upvote, remember to upvote dasblikenlight's answer as well.
class ViewController: UIViewController {
// Connect all 4 buttons to this outlet
#IBOutlet var radioGroup: [UIButton]!
// Connect this action to all 4 buttons
#IBAction func radioGroupClicked(sender: AnyObject) {
// Unhighlight all buttons
unhighlightRadioGroup()
// Highlight the one being clicked on
highlightRadioGroup(sender as! UIButton)
}
// Set all 4 buttons in unselected state
func unhighlightRadioGroup() {
for button in radioGroup {
button.selected = false
}
}
// Set one button in the selected state
func highlightRadioGroup(button : UIButton) {
button.selected = true
}
}
You can do it with an IBOutletCollection. Command-drag one of the buttons into the view controller code, and choose creating of an IBOutletCollection on drop, and name your collection something - say, radioGroup. Then control-drag the remaining three buttons into the same IBOutletCollection.
Next thing is to add a method to un-highlight all buttons in your radioGroup. This can be done with a simple loop.
Finally, add calls to unhighlightRadioGroup from the event handler of your buttons. Event handler should first call your unhighlightRadioGroup method, and then highlight the sender received in the event handler.
lazy var buttonsArray: [UIButton] = {
var buttons = [UIButton]()
let firstButton = UIButton()
let secondButton = UIButton()
let thirdButton = UIButton()
let fourthButton = UIButton()
buttons = [firstButton, secondButton, thirdButton, fourthButton]
return buttons
}()
private func setupButtonMethods() {
filteredButtons[0].addTarget(self, action: #selector(firstButtonPressed(sender:)), for: .touchUpInside)
filteredButtons[1].addTarget(self, action: #selector(secondButtonPressed(sender:)), for: .touchUpInside)
filteredButtons[2].addTarget(self, action: #selector(thirdButtonPressed(sender:)), for: .touchUpInside)
filteredButtons[3].addTarget(self, action: #selector(fourthButtonPressed(sender:)), for: .touchUpInside)
}
private func setupHiglightedStateOnButton(button: UIButton) {
for btn in buttonsArray {
btn.isSelected = false
btn.backgroundColor = .gray
btn.setTitleColor(.white, for: .normal)
btn.isUserInteractionEnabled = true
}
button.isSelected = true
button.backgroundColor = .yellow
button.setTitleColor(.black, for: .normal)
button.isUserInteractionEnabled = false
}
#objc func firstButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
#objc func secondButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
#objc func thirdButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
#objc func fourthButtonPressed(sender: UIButton) {
setupHiglightedStateOnButton(button: sender)
}
remember to call setupButtonMethods() inside viewDidLoad()

Swift Reload textfield from button action

I have a button that creates many more buttons with a textfield:
func CreateButtonWithIndex(index:Int) {
let newButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
newButton.setTitle(“Button”, forState: UIControlState.Normal)
newButton.addTarget(self, action: Selector("go:"), forControlEvents: UIControlEvents.TouchUpInside)
newButton.tag = index+1;
var textFieldButton: UITextField = UITextField()
textFieldButton.tag = index+1;
textFieldButton.text = “textfield”
self.view.addSubview(textFieldButton)
self.view.addSubview(newButton)
}
func go(sender: AnyObject) {
println(“ok press button“)
}
How can I detect the textfield corresponding to the button pressed?
convert the sender into a UIButton
#IBAction func go(sender: AnyObject) {
let yourButton = sender as UIButton
println(yourButton.titleLabel.text)
}
Even better, if you're certain that only buttons are going to call the "go" action, you could instead do this:
#IBAction func go(sender: UIButton) {
println(sender.titleLabel.text)
if(sender.titleLabel.text == "OK")
println("OK button was pressed")
}
And more information can be found in the "Comparing Strings" section of Apple's Strings & Characters Swift documentation and the #IBOutlet thing I found in this tutorial.
Subclass UIButton. Add a UITextField variable to the subclassed UIButton. Assign the new UITextField variable after you create the UIButton subclass.
UIButton subclass:
class TextFieldButton: UIButton {
var textField: UITextField! // use this to reference the related text field
}
The code in your other class:
func CreateButtonWithIndex(index:Int) {
let newButton = UIButton.buttonWithType(UIButtonType.System) as TextFieldButton // use our new subclass
newButton.setTitle(“Button”, forState: UIControlState.Normal)
newButton.addTarget(self, action: Selector("go:"), forControlEvents: UIControlEvents.TouchUpInside)
newButton.tag = index+1;
var textFieldButton: UITextField = UITextField()
textFieldButton.tag = index+1;
textFieldButton.text = "textfield"
newButton.textField = textFieldButton // set reference to the text field
self.view.addSubview(textFieldButton)
self.view.addSubview(newButton)
}
func go(sender: AnyObject) {
println("ok press button")
println(sender.textField) // now we can access the related text field
}