0

I hope that this question's answer is as simple as the question itself.

I have a sound effect in an AVAudioPlayer that I want to play when every button is pressed. Now rather than manually adding a target to play that audio file to every button in my code, is there a way where I can override the touchUpInside event method (perhaps in an extension category file) and send the call to the AVPlayer in addition to sending the call to the super?

I don't want to have to subclass if I don't have to. Is there a delegate method I can use?

Liftoff
  • 24,717
  • 13
  • 66
  • 119
  • 2
    Overriding base class methods in a category file are usually bad form – JiuJitsuCoder Jul 06 '13 at 04:09
  • Can you suggest another way? – Liftoff Jul 06 '13 at 04:10
  • Sure, create a subclass that adds the target in whichever init you see fit. – Mick MacCallum Jul 06 '13 at 04:11
  • Do you think that adding an init method in the category that overrides the `initWithFrame:` method and adds the target would work? Or is that bad practice? – Liftoff Jul 06 '13 at 04:12
  • @David, I agree with 0x7ffffff. You can shift+select all of the buttons in the nib or storyboard and set the subclass on all of them at once. – JiuJitsuCoder Jul 06 '13 at 04:13
  • But I'm not using IB... All buttons are added in code, which is why I wanted a solution that didn't involve me adding the same line of code to 100 buttons. – Liftoff Jul 06 '13 at 04:14
  • Are they added in a loop or individually? If you have 100 buttons with some commonality you should definitely be subclassing anyways. – JiuJitsuCoder Jul 06 '13 at 04:16
  • Well this is the only thing I have needed to add to the base UIButton class. Almost every button is added individually, except for a few here and there in the menus. I didn't see the need to subclass something that I didn't need to change. – Liftoff Jul 06 '13 at 04:17
  • It shouldn't be terribly difficult, just do a global find/replace on UIButton with your new subclass name. XCode will jump to every mention of UIButton and you can replace or skip it as needed. Just be sure to do a commit before the global replace! – JiuJitsuCoder Jul 06 '13 at 04:23
  • I went ahead and did that. It seemed to be the most effective way to do it. Ah well, at least it works. Thanks for the help! – Liftoff Jul 06 '13 at 04:26

2 Answers2

1

In such cases, the best way is to subclass the parent view of your button view. If you are adding the buttons in a UIView class, then subclass your class from UIView. So, you will have to change only one place in the code.

Now, in the subclass override this method:

- (void)didAddSubview:(UIView *)subview;

It will get called when any of the subviews will be added to it. Identify the proper subview in the method and do any processing over the subview which you want.

Apurv
  • 17,116
  • 8
  • 51
  • 67
1

From any class that has a reference to the view which contains the buttons as subviews, you can just iterate through all of the subviews and see which ones are UIButtons:

for (id subview in _buttonView.subviews)
    if ([subview isKindOfClass:[UIButton class]])
        [(UIButton *)subview addTarget:self 
                             selector:@selector:(playSound)    
                             forControlEvents:UIControlEventTouchUpInside];
pfleiner
  • 92
  • 4