iOS attaching callbacks and associating different sender possible? - iphone

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.

Related

Set UIButton instance highlighted

I have lots and lots of UIButtons, kept in a UIScrollView, all of which are dynamically tagged.
I can retrieve the button's properties, such as its tag, outside of its creation method by creating a reference to it. However, I am unable to set properties on the button, i.e. more specifically, I can't seem to setHighlighted.
Here is an example:
//UIButton is created elsewhere, i.e. UIButton *createdButton... createdButton.tag = 101
//Trigger method with createdButton as SENDER
- (void)highlightButton:(id)sender {
UIButton *buttonInstance = (UIButton *)sender;
int tag = buttonInstance.tag //use this to perform button-specific code
[buttonInstance setHighlighted:YES]; // <-- Not setting
}
Any ideas?
highlighted is typically a transient state, used to indicate that the user is touching the button. As such, it will often be re-set to NO by UIKit in the normal course of touch handling events. This seems particularly likely in your case since the method is called by an action on the button itself.
If you want to persistently change the appearance of a button, you should set selected rather than highlighted. You can set titles, images etc. for this control state (UIControlStateSelected) in the same way as you are setting them for UIControlStateHighlighted.

use two different control-event on UIButton

I have created one dynamic button in my application and I call the following method:
[btnactions addTarget:self
action:#selector(deleteview:)
forControlEvents:UIControlEventTouchDown];</b>
This deleteview method is used for delete the specific application view whenever I click the button.
Now, I want another method to call dynamically on button event
UIControlEventTouchDownRepeat
So how can I call two different events using different control events?
You can call addTarget again with UIControlEventTouchDownRepeat
From the docs (UIButton inherits from UIControl):
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
You may call this method multiple times, and you may specify multiple
target-action pairs for a particular event. The action message may
optionally include the sender and the event as parameters, in that
order.

iPhone: IBAction vs Selector

I have a Button1 which has IBAction. Also I set target and action for my button
- (void)setTarget:(id)target action:(SEL)action {
[self.Button1 addTarget:target action:action
forControlEvents:UIControlEventTouchUpInside];
}
So when I pressed the button firstly IBAction did what he should, and than action that I set to button. Is that order always be like that ?
If you are loading you view or view controller from a nib file then yes the pattern will always be the IBAction even first followed by the target you have added to the button.
In effect adding an IBAction in Interface Builder is really just telling IB to call ["UIControl" addTarget:"id" forControlEvents:"UIControlEvent"], and you can add multiple targets to a UIButton.
In effect your code will load everything from the NIB file first (if you are using initWithNib:named:), so this will call the addTarget function on the button first with the action you have specified in Interface Builder, then at some later point the setTarget function you have above will get called, which will add another target action to the button. A UIControls targets are stored in an array which is accessed in order and will trigger if control events are met in the order they were created in.
If you look in the header file for UIControl (the super class for UIButton) you will see that NSMutableArray* _targetActions is an array. So the order is guaranteed to fire like this unless you reorder this array after it is created at some point.

Can we use other object than self for button’s target?

Instead of self can we use another object with addTarget in this code:
[nextMonthButton addTarget:self
action:#selector(showFollowingMonth)
forControlEvents:UIControlEventTouchUpInside];
If yes what are those objects?
Yes.
The other object just has to respond to showFollowingMonth so typically it will be a custom class you have created.
It can be any object, but the button does not retain that object when you add it as a target, so your object will have to last around for as long as the button is around, and know to release itself when the button is deallocated. This is usually hard to do, unless that object is the controller of a view containing the button, or some object that belongs to such a controller.
It can be pretty much any object that is alive and is able to respond to the given selector.
However, for actions with a visual feedback where you need to manipulate the views, staying in the controller will be the best strategy anyway.

creating a reference for use in identifiying if a button was clicked

How is it possible create a reference for an uibutton to check if it was pressed and do something like make the value for that button true in order to be able to use that value later on. I heard of ivars but i havent seen any documentation on how to use them and im not sure if they would work for my ibaction uibutton...
This is really a fundamental question and a full explanation will take along time.
Basically, you need to understand the concept of MVC (Model-View-Controller). In this case, the "View" will be your UIButton created in Interface Builder. It needs to have a target/action setup to point to some "Controller". This will be a custom class you design that performs some action when the UIButton is released. This controller can also track finger up/down/move/drag and what not. This Controller will store the fact the button was pressed in a "Model" class.
Here is some more reading:
http://developer.apple.com/iphone/library/documentation/general/conceptual/devpedia-cocoacore/MVC.html
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html
In the simplest cases, this can be done with Core Data and IB without writing any code and simply making connections.