9

I have a view controller with a delegate method that should be called, but it doesn't?

NotifyingViewController.h

@protocol NotifyingViewControllerDelegate <NSObject>
@required
- (void)iWasAccepted;
@end

@interface NotifyingViewController : UIViewController

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

NotifyingViewController.m

-(void)someMethod{
        [self.delegate iWasAccepted];
        [self dismissViewControllerAnimated:YES completion:nil];
}

NotifiedViewController.h

#import "NotifyingViewController.h"  
@interface NotifiedViewController : UIViewController <NotifyingViewControllerDelegate>

NotifiedViewController.m

-(void)iWasAccepted{
    [self saveIntoDB];
    NSLog(@"DELEGATE RAN");
}

For some reason, the controller that should be notified isn't. The Notifying controller does dismiss meaning the method that alerts the delegate IS run, but the delegate doesn't run the function because it doesn't NSLog. Any ideas why?

Josue Espinosa
  • 5,009
  • 16
  • 47
  • 81
  • 3
    Where do you assign `NotifiedViewController` as `NotifyingViewController`'s delegate? – Mick MacCallum Nov 21 '13 at 23:52
  • Your `delegate` is a `weak` reference (as it should be); are you sure it has not become `nil` when you call it? – Arkku Nov 21 '13 at 23:52
  • @0x7fffffff: I thought you only need to do it in the UIViewController:NSObject<> part? Is there somewhere else I need to put it? Sorry, i'm new to delegate methods :) – Josue Espinosa Nov 21 '13 at 23:55

1 Answers1

25

You can't just specify that an object conforms to a protocol. You must also assign that object as the delegate. When you alloc/init the instance of NotifyingViewController, set its delegate to self and you should be fine.

NotifyingViewController *notifyingInstance = [[NotifyingViewController alloc] init];
[notifyingInstance setDelegate:self];

It is important to both do this, and specify that the class conforms to the protocol, which you're already doing with this line.

@interface NotifiedViewController : UIViewController <NotifyingViewControllerDelegate>

Additionally, when calling delegate methods, it's good practice to wrap the function calls in respondsToSelector: checks.

if ([self.delegate respondsToSelector:@selector(iWasAccepted)]) {
    [self.delegate iWasAccepted];
}
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • Could you explain why the lastly mentioned practice is recommended? – Darius Miliauskas Dec 01 '15 at 22:58
  • @DariusMiliauskas That's how you check at runtime that the delegate has actually implemented the method. Even if you mark a method as required in your protocol, you aren't actually forced to implement it (you'll only get a warning if you don't). And if you have an unimplemented delegate method (either optional or required), and you attempt to call that method, the runtime will through a `NSInvalidArgumentException` and complain about how an "unrecognized selector sent to instance." In short, this check allows you to only call the method if the delegate instance actually implements it. – Mick MacCallum Dec 01 '15 at 23:12
  • i implement it but not enter into condition if ([self.delegate respondsToSelector:@selector(iWasAccepted)]) { [self.delegate iWasAccepted]; } how to resolve it? – Shahbaz Akram Jan 23 '18 at 07:29