views:

2307

answers:

2

What's the best way for registering events for my UIView subclass, so that I can connect them to IBAction-s in interface builder?

Currently I've just got a standard UIView dropped onto my main view and I've set the class to "RadioDial" (my custom class). This displays the view fine, but I have no idea how to get events out of it.

Thanks

+2  A: 

Create a method in your view controller (if nothing else, you should have a RootViewController in you project). Let's say your method is

  -(void) buttonClicked { code code code }

In the controller's header file (for example RootViewController.h) you then put:

  -(IBAction) buttonClicked;

And in IB you right-click your button/radio dial/whatever. You will see a list of events and you can drag FROM the connector of the event you want your controller to receive, to the object in IB that represents the controler (probably First Responder). This depends on how your IB structure is set up, but it should be straightforward.

Another alternative is to learn how to create UIViews programatically, and forget about IB for the time being. Opinions are divided about whether it's better to learn to use IB at the outset, or whether it's better to learn how to do everything in code and save IB for later. In any case, it's necessary to learn both ways of setting up an interface at some point.

Felixyz
+2  A: 

Please clarify: do you mean that you would like Interface Builder to offer your view controllers to wire up custom events that your view subclass will be emitting (much like the Button controls allow you to wire up Touch Inside, etc)?

If you need this type of functionality, you will need to use a generalized 'delegate' property on your View combined with a protocol.

@protocol RadioDialDelegate
-(void)dialValueChanged:(id)sender
@end

@interface RadioDial
{
    id<RadioDialDelegate> radioDelegate;
}
@property (nonatomic, assign) IBOutlet id<RadioDialDelegate> radioDelegate;

This will allow the controller to wire up to the view (assuming it implements RadioDialDelegate) and receive any events that come out of the view. Alternatively, you can use an untyped delegate and in your View code, use a late bound call:

if([radioDelegate respondsToSelector:@selector(dialValueChanged:)]) {
    [radioDelegate dialValueChanged:self];
}
Jason
Yes, that's exactly what I mean. And the problem I'm having is creating those custom events for my view subclass. What's actually happening is that in the classes - (void) touchesMoved under certain conditions I'd like to fire and event and I'd like that event to be connectable to IBActions through IB.
I've edited my answer to reflect how to do this. You will need to utilize the delegate/protocol pattern in order to do that. IB will expose the delegate as a property that's assigned to your controller (you'll also need to set your controller class properly in IB), and your controller will need to implement the protocol.
Jason
That sort of makes sense (pretty new to the whole Objective-C/Cocoa thing), but how would this allow me to wire up each RadioDial-s value change event to a different method on the view controller?I understand that I could use the same method and do checking on the sender reference, but is that the only way?
You can use the integer 'tag' property to assign a constant value to each RadioDial in your view. Then check sender.tag in your controller event handler. That way, you don't need a reference to the RadioDial itself in the controller.
Jason
You'll need to use the valueChanged method as a dispatcher.. e.g. "switch(sender.tag) { case 1: [self r1changed]; break; ... }", since IB doesn't allow you to wire up custom selectors (just custom properties).
Jason