19
votes

This is just a quick question, mostly something I've noticed and been rather confused about. I've played with addTarget in the past, and noticed that if you're calling addTarget dynamically, and set the same target/action twice on say, a button - using addTarget method. Even though we "Added" a target and action more then once, regardless of them being the same target and action, the action itself is only called once.

So, my question - does addTarget ignore adding another target to itself if it already exists in it's stack of target/actions?

1
Why would you ever want/need to add the same target/action pair more than once to a button?rmaddy
You wouldn't. That's not the question. It's more of a question regarding naming consistency and why adding the same target twice does not do what you would expect the behavior to do.Braydon Batungbacal
Adding it twice and being called once is the expected behavior. It's the same for adding an observer to notification center. There is no reason to add more than once so if you do, it is ignored.rmaddy
@rmaddy, one place you do see a lot of people add it more than once (maybe unknowingly) is on buttons in a table view cell. I don't remember ever seeing a post where someone checked whether a button had an action already before adding the target and action in cellForRowAtIndexPathrdelmar
Just for the sake of completeness, this would lead to the question, wether removing a target fails if that target has not been added before (which is usually the case, if the cell is dequeued for the first time. :-)Christian

1 Answers

26
votes

UIButton is a UIControl object, which follows an event-listener pattern, which is often implemented with a hashmap (NSDictionary in Objective-C) of targets (aka Listeners or Observers). Since a target is added as a key, it is guaranteed not to be added more than once.

The documentation for addTarget:action:forControlEvents: of UIControl describes this behavior as a safety feature:

It is also safe to call this method multiple times with the same values for the target and action parameters. The control maintains a list of its attached targets and actions along [with] the events each supports.

To disable response for a given control event, the discussion states that you must remove the target-action registration, which is analogous to removing a key from a hashmap:

Specifying a value of 0 for the controlEvents parameter does not prevent events from being sent to a previously registered target and action method. To stop the delivery of events, always call the removeTarget:action:forControlEvents: method.