Question

I am trying to develop a control that will mimic the behaviour of a UITableView control. I have defined a delegate protocol as follows:

@protocol HPSChoiceDelegate

- (void)choiceView:(HPSChoice *)choiceView didSelectChoice:(NSNumber*)selectedIndex;

@end

The user can tap subviews within the main control view. I have TapGesture recognisers in place that fire methods within the main control view. I wire these up like this:

UITapGestureRecognizer *containerTap = 
        [[UITapGestureRecognizer alloc] initWithTarget:self
                                                action:@selector(didSelectChoice:)];

I then have a method in the view that attempts to call the correct method in the delegate. The method in the view looks like this:

-(void)didSelectChoice:(UITapGestureRecognizer*)sender
{
    NSNumber* selectedIndex = [NSNumber numberWithInt:sender.view.tag];

    [(id)self.delegate performSelector:@selector(didSelectChoice:) withObject:selectedIndex afterDelay:0.0f];
}

In the delegate controller I have the following method defined:

- (void)choiceView:(HPSChoice *)choiceView didSelectChoice:(NSNumber*)selectedChoice
{
    NSLog(@"HPSFormController didSelectChoice:(HPSChoice*)choiceView tag = %@",[[choiceView class] description]);
}

It all compiles, and when I tap the control then the didSelectChoice is called in the view which then calls the method in the delegate. However, the delegate method crashes with the following error:

-[HPSFormController didSelectChoice:]: unrecognized selector sent to instance 0x29b4e0

How do I fix this? Thanks very much.

Was it helpful?

Solution

The method is crashing because you are calling

didSelectChoice:

while the method that you defined is

choiceView:didSelectChoice:

I believe that you can fix this by calling:

[(id)self.delegate performSelector:@selector(choiceView:didSelectChoice:) withObject:choiceView withObject:selectedIndex];

You would have to get the choiceView in your didSelectChoice: method of course.

OTHER TIPS

If your view, for example, is called HPSChoiceView, you need also to say that its delegate it's the controller where you create that view.

For example, somewhere within the delegate controller (HPSFormController I suppose) you need to do:

HPSChoiceView* choiceView = // alloc-init here
// self refers to an instance of HPSFormController at run-time
choiceView.delegate = self;

This implies that each time you tap in that view, the controller will respond to that tap since it has been set as its delegate.

In addition you are calling the wrong selector. Instead of calling

[self.delegate performSelector:@selector(didSelectChoice:) withObject:selectedIndex afterDelay:0.0f];

call

[self.delegate performSelector:@selector(choiceView:didSelectChoice:) withObject:choiceView withObject:selectedIndex];

choiceView can be retrieved from sender.view. sender is an istance of UITapGestureRecognizer and for this reason you can retrieve the view that was tapped.

To understand what a selector is you could see Selectors in Objective C and Apple doc.

Said this, I would also change the selector for you delegate HPSChoiceDelegate. So, for example, I would call it (just for clarity):

- (void)didSelectChoiceView:(HPSChoice *)choiceView withSelectedIndex:(NSNumber*)selectedIndex;

If you use this, the selector will be didSelectChoiceView:withSelectedIndex:. Pay attention to colons!!

Furthermore, I would add a control before calling a delegate method as the one suggested by @Cirylle. That control allows you to verify if you set the delegate (first part of my answer) and the delegate can respond to that selector since it has been implemented correctly.

Hope that helps.

The class that should act as delegate must declare and conform to the HPSChoiceDelegate protocol and it must also register itself as the delegate of your UITableView'ish class.

Also, try changing to @selector(choiceView:didSelectChoice:).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top