How Does Uibutton Addtarget Self Work

How does UIButton addTarget self work?

addTarget:action:forControlEvents: tells the control (answerButton in this case) what method to call, and what object to call it on, when the user taps the button. Looking at your code in more detail:

 answerButton.addTarget(self, action: "didPressAnswerButton:", forControlEvents: .TouchUpInside)
  • When the user taps a button, the TouchUpInside event fires on the answerButton, and when that happens we want to invoke a method didPressAnswerButton: on an Answer object
  • So, we need to tell answerButton what do do when this TouchUpEvent fires. You do this calling the addTarget:action:forControlEvents method on the answerButton
  • The self argument tells the answerButton what object to notify about the event: it is the target. In this context, self is an Answer object.
  • The "didPressAnswerButton:" argument indicates what method the answerButton should call in response to the tap event: this is the action

This is the target-action mechanism of Objective-C/Cocoa. It's a very common pattern, it's worth it to read the linked documentation to learn a bit more about how it works. The key is that this is based on Objective-C* message passing: in the code above, "didPressAnswerButton:" indicates a selector, which when paired with a target (self), tells the answerButton how to send a "message" to the target when the user taps the button.

Also, note that when you are editing a storyboard and ctrl-drag from a button to your view controller and select a method, you are also setting up a target/action using this same mechanism. You select the target object by dragging to the view controller icon (or some other icon), and then you pick the action/selector when clicking on a method name in the popup.

* Target-Action was originally designed for Objective-C, but for the common case of implementing a view controller, you can assume Swift works the same way. Just note when reading documentation that Swift uses simple strings for actions, whereas Objective-C uses @selector(...).

Dynamic Creation UIButton AddTarget on UIView executed on UIViewController

In the method button.addTarget(self, action: #selector(optionClicked(_:)), for: .touchUpInside) you need to provide pointer to the viewController which will receive the action.

The easiest way in your case would be to create lazy variable DrawerView with DrawerController on the init and use the drawer controller in the button action.

DrawerView.swift

class DrawerView: UIView {

private unowned let drawerController: DrawerController

init(drawerController: DrawerController) {
self.drawerController = drawerController
}

... wherever is your code placed ...

let menuOptions = ["Info", "Actions", "Users", "Patiens"]

menuOptions.forEach({

let button = UIButton()
button.setTitle($0, for: .normal)

if $0.contains(menuOptions[0]) {
button.style(with: .filled)
} else {
button.style(with: .outlined)
button.addTarget(drawerController, action: #selector(DrawerController.optionClicked(_:)), for: .touchUpInside)
actionStackView.addArrangedSubview(button)
}
})

....
}

It's important you use unowned or weak to prevent retain cycles and memory leaks

To create the DrawerView you can use a lazy variable:

lazy var shareView: DrawerView = DrawerView(drawerController: self)

lazy will allow you to use self, you can also use optional and create the variable later, but that's basically what lazy does.

Hope it helps!

UIButton add target without sender

Using Any as sender type and casting to Date works

//add button Target
btn.addTarget(self, action: #selector(goToNextScreen(_:)), for: .touchUpInside)

//Call with date value
goToNextScreen(Date())

@objc func goToNextScreen(_ selectedDate: Any) {
nextVC.date = selectedDate as? Date
//...
}

UIButton addTarget:action:forControlEvents: not working using itself as a target?

Its not working bcoz you are adding self as target. You need to add Your ViewController as target on which you button is added.

[self addTarget:viewController action:@selector(onClick:forEvent:) forControlEvents:UIControlEventTouchUpInside];

addTarget:self versus addTarget:nil

If you add self or any other object as the target for an action message the message will be sent to exactly this object.

Adding nil as a target means that the actual target will be searched at runtime when the message is triggered. The lookup starts at the first responder object and continuous from there along the responder chain, that is by trying the object returned by the nextResponder method until an object is found that implements this method. Take a look at the event handling guide for more information on the exact lookup order.

Action of UIButton doesn't work if the button is initialized with let and the addTarget in it in custom view, but it works in UIViewController

self inside that block actually is the block, not the view(you can see it using print(self)), probably because it's not yet initialised(same reason why you can't use self before super.init), that's why I usually add targets/delegates outside of the initialisation block. With lazy var self is already initialised, so no problem should be there.

I'm not sure why it works at all, seems kind of magic for me, and I wouldn't depend on it.

Anyway, it works fine with both custom ViewController and custom View in my case: I've added CustomView as subview to ViewController in the storyboard.

class ViewController: UIViewController {

private let usernameButton: UIButton = {
let button = UIButton(type: .system)
button.setTitleColor(.black, for: .normal)
button.setTitle("someTitle", for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 13)
button.addTarget(self, action: #selector(didTapUsername), for: .touchUpInside)
return button
}()

override func viewDidLoad() {
super.viewDidLoad()
view.insertSubview(usernameButton, at: 0)
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
usernameButton.frame = view.bounds
}

@objc
func didTapUsername() {
print("ViewController", #function)
}
}

class CustomView: UIView {
private let usernameButton: UIButton = {
let button = UIButton(type: .system)
button.setTitleColor(.black, for: .normal)
button.setTitle("someTitle", for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 13)
button.addTarget(self, action: #selector(didTapUsername), for: .touchUpInside)
return button
}()

override func awakeFromNib() {
super.awakeFromNib()
addSubview(usernameButton)
}

override func layoutSubviews() {
super.layoutSubviews()
usernameButton.frame = bounds
}

@objc
func didTapUsername() {
print("CustomView", #function)
}
}

This shouldn't do differently for UIViewController/UIView, check out your logic



Related Topics



Leave a reply



Submit