Question

I have a property on a ViewController which I set from a parent SplitViewController:

Property declaration/synthesization

@interface DownloadRecipesViewController_iPad : DownloadRecipesViewController<PopoverMenuDelegate, RecipeChangeDelegate>{
    id <NSObject, PopoverMenuParentDelegate, RecipeChangeDelegate, RecipeDownloadedDelegate> _selectionDelegate;
}

@property (strong) UIBarButtonItem *btnMenu;
@property (strong) id <NSObject, RecipeChangeDelegate, RecipeDownloadedDelegate> selectionDelegate;

@implementation DownloadRecipesViewController_iPad

@synthesize btnMenu;
@synthesize selectionDelegate = _selectionDelegate;

I wire up the delegate in the parent SplitViewVC's viewDidLoad method:

Wiring up the delegate

self.downloadVc = [self.storyboard instantiateViewControllerWithIdentifier:@"RecipeDownload"];
[self.downloadVc setSelectionDelegate:self];

A button in the Child VC calls a method to fire an event up to the parent ViewController, but when this event is called, the delegate is nil and the event isn't fired. I've wracked my brains trying every which way to find out why this happens but I'm at a total loss.

Delegate is nil here (firing the delegate):

-(IBAction)didTapMenu:(id)sender{
    if([_selectionDelegate respondsToSelector:@selector(shouldToggleMenu)])
        [_selectionDelegate shouldToggleMenu];
}

I've also tried without the backing property but hit the same problem.

Was it helpful?

Solution

Suggestions on how to find this follow. But first, why not save yourself some typing and remove the ivar and remove the @synthesize - its totally unnecessary typing at this time. Also, as a comment said, delegates should almost always be typed as weak.

Suggestions:

1) Write a (temporary) setter for the selectionDelegate, then set a break point where you actually set the value (or after) so you can verify that its getting set, and that nothing else is zeroing it out.

2) Set a breakpoint on the IBAction method, on the line where the if statement is, and when you hit it verify the object is the same one where you set the delegate, what the delegate value is, and then see if the respondsTo method succeeds (use single step).

OTHER TIPS

The way I eventually solved this was:

  1. Create a new delegate which exposes a method: -(void)segueBeginning:(UIStoryboardSegue*)destination
  2. Use this delegate to expose prepareForSegue from the child UINavigationController to the parent SplitViewController .3. Hook up my child VC in the parent ViewController when prepareForSegue is raised in the child nav controller:

    if([destination.destinationViewController isKindOfClass:[DownloadRecipesViewController_iPad class]] && !self.downloadVc){ // download recipes
        self.downloadVc = destination.destinationViewController;
        self.downloadVc.selectionDelegate = self;
        [self.downloadVc setSnapshotChangeDelegate:self];
        [self.downloadVc.navigationItem setRightBarButtonItems:[NSArray arrayWithObjects:btnAdd, nil]];
    }
    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top