addTarget:self versus addTarget:nil - iphone

I am new in iOS development. I am little confuse when I am adding a button programmatically.When we assign a target to button like:
[button addTarget:self action:#selector(CallMe) forControlEvents:UIControlEventTouchUpInside];
and
[button addTarget:nil action:#selector(CallMe) forControlEvents:UIControlEventTouchUpInside];
It is calling CallMe method in both the cases. Can anybody explain me what is the actual difference between these two lines of code.It will more helpful if anyone can explain the working of addTarget specially.Thank you very much. Help would be appropriated.

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.

According to Apple's documentation,
The target object is the parameter send to addTarget method—that is, the object to which the action message is sent. If this is nil, the responder chain is searched for an object willing to respond to the action message.
If you want to remove the action, you can pass nil to remove all targets paired with action and the specified control events on the remove target method,
[button removeTarget:nil action:#selector(CallMe) forControlEvents:UIControlEventTouchUpInside];

Here is description of parameter Target from apple's documentation for UIControl class:
target
The target object—that is, the object to which the action message is sent. If this is nil, the responder chain is searched for an object willing to respond to the action message.

Related

how to pass data through #selector upon custom button click?

I'm making a button via code.
I have the following line of code to trigger a method when the button is clicked:
[imagesButton addTarget:self action:#selector(photoClicked:) forControlEvents:UIControlEventTouchDown ];
The problem is that I can't pass data to the method through the #selector;
If the button had a background image name "background.png" how would I go about sending the name of the background image to the method when the button is clicked?
This all HAS to be through code.
Thanks!
-Shredder
there must be a way to comment on an answer, but I don't know what it is. Anyway, Gobot above me forgot to write (id) before sender in the method declaration. Otherwise Gobot's example is ok.
Well if you're trying to change a property of the button whose sending the message, your selector should have a parameter of sender, which is a pointer to the object that called it, which is your button in this case. For example:
- (void)photoClicked:(id)sender {
UIImage bg = [sender currentBackgroundImage]
}

iOS attaching callbacks and associating different sender possible?

Suppose I have a button that I am adding to an annotation object in a mapview:
AnnotationButton* rightButton = [AnnotationButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
You will notice that the button calls the function showDetails when it is clicked.
Show details is defined as - (void)showDetails:(id)sender; and takes a sender. Is there a way to send more variables, or associate a different sender? The reason is that I want the button clicked to tell me which annotation is associated with that button. Consider the annotation to be some other object which is available during the context where the button is created.
I thought about subclassing the UIButton class, and then storing additional information within it, but that seems like a hack.
Any ideas?
If this button is being used for the rightCalloutAccessoryView or leftCalloutAccessoryView of a MKAnnotationView, your map's delegate should receive the message mapView:annotationView:calloutAccessoryControlTapped: when the button is tapped. This hands you the MKAnnotationView instance that was tapped, which has an annotation property to give you the corresponding annotation. You should make use of that instead of trying to use an action on the button directly.
No, there is no way to change what is sent to the action message. You can ask for two arguments, but they will be the button and the event that triggered it. To get what you want, you have two options (that I can think of now).
Use the button's tag property. You can give each button a unique tag which identifiies the annotation, such as the index of the annotation in an array. Then it is easy to get the annotation in your showDetails: method.
Subclass UIButton. There is nothing wrong with adding functionality to built in objects. All you need to add is a property to hold some object. Bonus: If you use a generic id type for the property and give it a generic name, such as representedObject, you can use it in other projects in the future too.
from Anomie Use objc_setAssociatedObject to add a value to the buttons without subclassing. You will probably want to add a category to UIButton to make it easier to use.

Simple UIButton Question

I have 1 button and 2 methods. One method calls this:
[button addTarget:self action:#selector(action1) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
And the other calls this:
[button addTarget:self action:#selector(action2) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
For some reason, the button's action will not change. I am sure I am calling the above code correctly. Is it trying to add an action to the button and making it call both functions? If so, how can I stop this from happening? I have tried releasing and setting the button to nil before setting the new action and no luck. Thanks for the help.
Yes. It's actually calling action1 and action2. You need to call removeTarget before adding the new target on the button.

Connect touch event in ios

Now that I know that NSEvent does not exist on ios - what do I need to do to capture an event like touchUpInside and cause it to call my method to handle it, WITHOUT Interface Builder?
I think this like asking how do I link an event to an outlet without IB...
I know it can be done, but I can't find anything that shows how - except Mac-only examples that use NSEvent.
Take a look at this method in UIControl:
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
Each of the different event types has a constant, such as UIControlEventTouchUpInside. Here's an example of it being used:
[addButton addTarget:self action:#selector(increment:) forControlEvents:UIControlEventTouchDown];
Look here for the values of controlEvents, listed in the Constants section.

Calling a method which is also used by UIButton?

I have a small iPhone app which I've created a button with some functionality in. My question is, how can I call this button without actually pressing it?
Any help would be appreciated!
Thanks
If you want to activate whatever target a button is wired to, you can call:
[button sendActionsForControlEvents:UIControlEventTouchUpInside];
(TouchUpInside is the event you'd normally wire a button action to). This way if other targets are added or changed for any button (say for debugging) you don't have to alter your code.
This method is on UIControl which UIButton inherits from, which is why you might have overlooked it at first glance...
Have your button event call a function. You can also manually call the function yourself.
Example:
- (void) btnFunction {
NSLog (#"test");
}
...
UIButton *btn1 = [UIButton buttonWithType:UIButtonRoundedRect];
// other code to set up button goes here
[btn1 addTarget:self action:#selector(btnFunction) forControlEvents:UIControlEventTouchUpInside];
You can also call the function yourself:
[self btnFunction];
Your button shouldn't have functionality, it should just send a message to its target (or call a method, or call a function...).
You're free to send that message to that target yourself.
e.g. Your button's target outlet is connected to an IBAction on your controller. That IBAction is just a method of the form:
- (void) doSomething:(id)sender
In your own code do:
[controller doSomething:self];
It's exactly the same as having your button do it.