2

I think I'm following how delegation works, here's the tutorial I followed, but I'm messing up somewhere. I'm expecting my delegate to NSLog but it's not. Can anyone find out what am I missing or doing wrong?

My MainViewController.h:

@interface MainViewController : UITableViewController < AddClassDelegate >

MainViewController.m:

- (void)cancelAddingClass {
    NSLog(@"Canceled Yo");
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

/*
 When a row is selected, the segue creates the detail view controller as the destination.
 Set the detail view controller's detail item to the item associated with the selected row.
 */
if ([[segue identifier] isEqualToString:@"addClassSegue"]) {

    UINavigationController *nc = (UINavigationController *)segue.destinationViewController;
    AddClassViewController *addClassVC = (AddClassViewController *)[nc.viewControllers objectAtIndex:0];
    addClassVC.delegate = self;
}

My modal view controller AddClassViewController.h:

@protocol AddClassDelegate <NSObject>
- (void)cancelAddingClass;
@end

@interface AddClassViewController : UITableViewController

@property (weak, nonatomic) id< AddClassDelegate > delegate;

- (IBAction)cancelButtonPressed:(id)sender;

AddClassViewController.m:

@synthesize delegate;

- (IBAction)cancelButtonPressed:(id)sender {
    [self.delegate cancelAddingClass];
}

cancelButtonPressed: 

is hooked up to the modal view's Cancel button in Storyboard.

tazboy
  • 1,685
  • 5
  • 23
  • 39
  • this should work... try to NSLog delegate object before ` self.delegate cancelAddingClass ` and see if it is not null.. – Shubhank Mar 08 '12 at 13:35
  • Ok, so that's not good. My delegate = null. – tazboy Mar 08 '12 at 13:40
  • i think this might be because of weak reference in delegate declaration ... try changing it to strong – Shubhank Mar 08 '12 at 14:04
  • Are you sure that `if ([[segue identifier] isEqualToString:@"addClassSegue"])` is actually true? Is the `NSLog` statement 'NSLog(@"segued")' actually firing? Maybe you misnamed the segue in the storyboard. – Gobot Mar 08 '12 at 15:51
  • I tested the segue and it works. – tazboy Mar 08 '12 at 23:24

3 Answers3

2

Your code looks fine, which suggests the problem is somewhere we can't see. My guess is here:

AddClassViewController *addClassVC = [segue destinationViewController];
addClassVC.delegate = self;
NSLog(@"segued");

Have you embedded your modal view controller in a navigation controller? If so, destinationViewController gives you the navigation controller, not the AddClassViewController. Check what class addClassVC actually is in the debugger.

If it is a navigation controller, no problem, you just need to get to your actual VC using the .viewControllers property. On several lines to make it simpler to understand:

UINavigationController *nc = (UINavigationController *)segue.destinationViewController;
AddClassViewController *addClassVC = (AddClassViewController *)[nc.viewControllers objectAtIndex:0];
addClassVC.delegate = self;

You can do it in fewer lines but it's a mess of casting and nested brackets, which is harder to debug.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • I think that's my problem because I NSLogged addClassVC's class and it said it was a navcontroller. I tried AddClassViewController *addClassVC = [[segue destinationViewController] rootViewController]; but it gives me a warning:Semantic Issue: Incompatible pointer types initializing 'AddClassViewController *__strong' with an expression of type 'UIViewController *' – tazboy Mar 08 '12 at 23:42
  • I get an error stating Property 'rootViewController' not found on object of type 'UINavigationController *'; did you mean 'topViewController'? I also tried topViewController but my app crashed. Thanks for the continued help. – tazboy Mar 09 '12 at 13:07
  • Oops, that's what I get for answering on my phone without checking the docs... answer updated – jrturton Mar 09 '12 at 13:14
  • Hmm. Now my app is crashing. Here's the error I get: [AddClassViewController viewControllers]: unrecognized selector sent to instance – tazboy Mar 09 '12 at 16:02
  • Can you update the question with your current prepareForSegue implementation. You shouldn't be seeing that if you've used the code in my answer, but I know you've put lots of changes in there so it's hard to help. – jrturton Mar 09 '12 at 16:50
  • Does it matter that my AddClassViewController is a UITableViewController as opposed to a UIViewController? – tazboy Mar 09 '12 at 18:35
  • No. The error you're now getting is inconsistent with your earlier statement that the destination view controller is a navigation controller. Have you changed the storyboard or something since this question started? – jrturton Mar 09 '12 at 18:57
  • You are doubly correct! I removed the navigation controller in my storyboard to test something out last night. Now that that's back and the code you provided is in place, everything works great. Thanks for the time. It's appreciated. – tazboy Mar 09 '12 at 19:12
  • Phew! That was turning into a bit of a epic. – jrturton Mar 09 '12 at 19:46
  • Great spot - I've just used this to solve the same problem with a stray navigation controller! Thank you and upvoted. – krider2010 Aug 24 '12 at 10:34
0

Is it possible your main view controller is being released? That would set the weak reference to nil and the message you send to your delegate would simply be ignored because you'd be messaging nil.

Jim
  • 72,985
  • 14
  • 101
  • 108
-1

Everything is perfect. I haven't seen any issue. Keep break points everywhere and debug it.

Dee
  • 1,887
  • 19
  • 47
  • If I throw in breakpoints, what would I be looking for? I don't have any errors. It just doesn't work as expected. – tazboy Mar 08 '12 at 13:43
  • breakpoins won't give you information about application errors. you can check whether the respected method is getting called or not if you keep break points. – Dee Mar 08 '12 at 13:46
  • If all you needed was to see if a method is being called wouldn't NSLog statements be sufficient? I can see how breakpoints would be useful for getting an understanding the order your program works and such. I should try them more. – tazboy Mar 09 '12 at 01:08
  • If you use NSLog's all the time you need to check console .. whether that log has been printed or not. Instead If you use break points, you will easily come to know that this method has been called & its up to you to decide which one to use. – Dee Mar 09 '12 at 07:13
  • I asked you to use breakpoints because, I thought some of your methods are not being called. If you start writing NSLog's in each method to check whether it is being called or not it will increase number of lines in your code. To check whether you are getting proper reference to your instance variables you can use NSLog's. – Dee Mar 09 '12 at 07:24