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?
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];
}
Related
With these codes, I set the delegate for the ViewController that is about to be presented. Based the logged result, the delegate is not nil when is assigned to the viewController.
NewEventViewController *NewEventView = (NewEventViewController *)[[self storyboard] instantiateViewControllerWithIdentifier:#"AddView"];
NewEventView.delegate = self;
NSLog(#"delegate %#", NewEventView.delegate);
[self presentViewController:NewEventView animated:YES completion:nil];
Here is my declaration of protocol in NewEventViewController.
#protocol NewEventDelegate <NSObject>
-(void)addNewEventToProject:(Events *)event;
-(void)addProject:(Projects *)project;
#end
I declared a delegate like this
#property (nonatomic, assign) id <NewEventDelegate> delegate;
When the viewController is presented, the delegate seems to be nullified. I logged the delegate with NSLog(#"Delegate %#", self.delegate); the outcome is Delegate (null) What is the problem in my code.
My purpose is to call the delegate method when the viewcontroller is dismissed. The delegate method will pass back a Event object that will be added to my Realm database. Thank you very much!
Look at the following code.
In CusFormViewController.h
#interface CusFormViewController : CusBaseViewController
#protocol CusFormViewControllerDelegate <NSObject>
-(void)ticketCreated:(NSString*)ticketID;
-(void)ticketFormRenderingFinished;
#end
#property (nonatomic, weak) id<CusFormViewControllerDelegate> delegate;
In CusFormViewController.m
if ([self.delegate respondsToSelector:#selector(ticketFormRenderingFinished)])
[self.delegate ticketFormRenderingFinished];
if ([self.delegate respondsToSelector:#selector(ticketCreated:)])
[self.delegate ticketCreated:ticket_id];
In ViewController.m
#import "CusFormViewController.h"
#interface ViewController ()<CusFormViewControllerDelegate>
- (void)viewDidLoad {
[super viewDidLoad];
CusFormViewController *formVC = [[CusFormViewController alloc] init];
[formVC setDelegate:self];
}
-(void)ticketCreated:(NSString*)ticketID{
NSLog(#"ticket created.");
}
-(void)ticketFormRenderingFinished{
NSLog(#"ticket form rendered.");
}
The ticketCreated & ticketFormRenderingFinished are not being called.
Most common reason for delegate method not being called is dealing with incorrect objects.
Ensure that CusFormViewController object created from
ViewController is the same which you are presenting on screen and
that the delegate is being set on the same object. I truly believe
you are creating a new CusFormViewController object and setting
delegate on that.
In CusFormViewController, before calling delegate, check the
existence of delegate as well. This is a safety check, you can also put a
NSLog statement to double check if your delegate exists or not. You
are failing here.
If you are segueing from ViewController to CusFormViewController then you set delegate in prepareForSegue: and not in viewDidLoad.
As a side note, put a NSLog statement in viewDidLoad of your CusFormViewController and print self.delegate to check the property setting.
Your controller formVC is dealloced after the function viewDidLoad executed. Create strong reference on your formVC for example like this:
#interface ViewController ()<CusFormViewControllerDelegate>
{
CusFormViewController *_formVC;
}
- (void)viewDidLoad {
[super viewDidLoad];
_formVC = [[CusFormViewController alloc] init];
[formVC setDelegate:self];
}
Hey try to create instance of CusFormViewController using below method
CusFormViewController * _formVC=[[UIStoryboard storyboardWithName:storyboardName bundle: nil]instantiateViewControllerWithIdentifier:#"IDENTIFIER_OF_YOUR_ CusFormViewController"];
I've make a delegate so my two different view controllers can communicate and I'm stuck trying to set a BOOL to YES in my child view controller.
childViewController.h
#protocol pageTwoViewControllerDelegate;
#interface pageTwoViewController : UIViewController {
UIButton *takePhotoTransition;
}
#property (nonatomic, weak) id<pageTwoViewControllerDelegate> delegate;
#end
#protocol pageTwoViewControllerDelegate <NSObject>
- (BOOL)didPushTakePhoto;
#end
childViewController.m
...
- (IBAction)takePhotoTransition:(id)sender {
id<pageTwoViewControllerDelegate> strongDelegate = self.delegate;
if ([strongDelegate respondsToSelector:#selector(didPushTakePhoto)]) {
strongDelegate.didPushTakePhoto = YES; // ERROR: No setter method for 'setDidPushTakePhoto:' for assignment property
}
NSLog(#"Button push recieved");
}
How can I get past this error and set my BOOL to YES when my button is pushed?
The protocol is just telling everyone that knows about your class through the protocol, that the property anObject will be there. Protocols are not real, they have no variables or methods themselves
Try to modify your code to be like this, you are setting a non existence variable or property.
you have to implement new Class instead of id
your protocol will look like
#protocol pageTwoViewControllerDelegate <NSObject>
- (void)setdidPushTakePhoto:(BOOL)aBOOL;
- (BOOL)didPushTakePhoto;
#end
and your class.h will contain
#property (nonatomic, getter=get_didPushTakePhoto) BOOL didPushTakePhoto;
and your class.m will contain implementation
-(BOOL)didPushTakePhoto
{
return _didPushTakePhoto;
}
- (void)setdidPushTakePhoto:(BOOL)aBOOL{
_didPushTakePhoto=aBool;
}
You are getting confused between a method and a property.
The definition of your protocol "pageTwoViewControllerDelegate", says it should implement a method with name "didPushTakePhoto" which returns a BOOL value.
What you are trying to do is entirely different. You are trying to set a non-existent property. Whenever you are accessing something followed by a dot ".", that should be a property of the class to which that object belongs. The protocol you defined does not talk anything about the property.
So inside the if condition, you should be calling the method "didPushTakePhoto" on your delegate object, like below.
[strongDelegate performSelector:#selector(didPushTakePhoto)];
If you know for sure that your delegate implementations do have the protocol method implemented, then since you already cast self.delegate to strongDelegate which is declared as id, you don't need the if condition. You could directly call the method like below.
[strongDelegate didPushTakePhoto];
Hope this helps
Have you assigned the delegate of your ChildViewController belongs to ParentViewController?
Try this:
ParentChildViewController.m
#import "ChildViewController.h"
#interface ParentViewController () <ChildDelegate>
...
-(IBAction)btnClicked:(id)sender
{
ChildViewController *ctrl = [[ChildViewController alloc] init];
ctrl._delegate = self;
// do present childViewController or similar action here
}
- (void)didPushTakePhoto: (BOOL)result{
NSLog(#"result: %d",result);
}
ChildViewController.h
#protocol ChildDelegate
- (void)didPushTakePhoto: (BOOL)result;
#end
#interface pageTwoViewController : UIViewController {
UIButton *takePhotoTransition;
}
#property (assign, nonatomic) id _delegate;
#end
ChildViewController.m
...
- (IBAction)takePhotoTransition:(id)sender {
if ([self._delegate respondsToSelector:#selector(didPushTakePhoto:)]) {
[self._delegate didPushTakePhoto:YES];
// do dismiss here
}
}
I have two controllers. A BaseViewController and MyController. On BaseViewController I have as property an NSObject that has a Protocol
BaseViewController.h
#property (nonatomic, strong) MyListener *myListener;
MyListener.h
#protocol MyListenerProtocol;
#interface MyListener : NSObject
#property (nonatomic, weak) id<MyListenerProtocol> delegate;
#end
#protocol MyListenerProtocol;
#protocol MyListenerProtocol <NSObject>
#optional
-(void) myMethod: (int) input;
#end
MyController extends BaseViewController
#interface MyController : BaseViewController <MyListener>
and in it's viewDidLoad:
super.myListener = [[MyListener alloc] init];
super.myListener.delegate = self;
in BaseViewController in a method, when called it does:
if (self.myListener && [self.myListener.delegate respondsToSelector:#selector(myMethod:)]) {
[self.myListener.delegate myMethod: input];
}
But in this point the "self.myListener" is always nil.
What I want is to call a method in the child view controller when a BaseViewController's method is called (but only for some children view controllers, not all).
Any suggestions?
Please implement a custom getter for the property named delegate, set it normally and set a breakpoint there. This way you will find the cause of the problem.
Also, be aware that a weak property will go away as soon as no other objet points to the
Object that you set as delegate.
The most likely cause (and an insanely common cause) is that your BaseViewController method is being called prior to viewDidLoad. Have you verified this is not the case?
As a note, you mean self in all the places you've put super.
Also note, in this line:
if (self.myListener && [self.myListener.delegate respondsToSelector:#selector(myMethod:)]) {
There is no reason for self.myListener &&... If self.myListener is nil, the rest of the call will become false automatically.
You should tell the MyController the delegate it uses, but you tell the wrong name.
#interface MyController : BaseViewController <MyListener>
change to:
#interface MyController : BaseViewController <MyListenerProtocol>
Set delegate in prepareForSegue method.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
LastNameViewController *lastNameViewController = [segue destinationViewController];
lastNameViewController.delegate = self;
}
i have created a delegate for my project the code of my main view is
VedantViewController.h
#protocol VedantDelegate;
#interface VedantViewController : UIViewController
{
id <VedantDelegate> delegate;
}
//some other outlets
#property(nonatomic, assign) id <VedantDelegate> delegate;
#protocol VedantDelegate <NSObject>
- (void)display:(NSString *)JSONResponse;
#end
VedantViewController.m
#synthesize delegate;
[delegate display:jsonResponse];
SecondViewController.h
#interface SecondViewController : UIViewController<VedantDelegate>
- (void)display:(NSString *)JSONResponse;
SecondViewController.m
- (void)display:(NSString *)string
{
}
but this code is not working properly
when i debug the code using breakpoints the code reaches the
[delegate display:abc];
but it does not calls display function in SecondViewController.m file
i think my code is right but some mistake that i can't recognize
let me explain you the flow of my project this could be the problem
by default the VedantViewController view is launched
after that when the show button is click it calls the SecondViewController view in the view these is list button that calls the function in VedantViewController this function then calls the delegate method that is [delegate display:jsonResponse];
Thanks in Advance,
Arun.
The view controller which is confirming with the protocol, should have this line in the viewDidLoad or anywhere you are making the object of that viewController
Add this line in SecondViewController.m
VedantViewControllerObject.delegate = self;
#protocol VedantDelegate;
#interface VedantViewController : UIViewController{
id<VedantDelegate> delegate;
}
//some other outlets
#property(nonatomic,assign) id<VedantDelegate> delegate;
#protocol VedantDelegate <NSObject>
-(void)displayAccounts:(NSString *)JSONResponse;
-(void)display:(NSString *)JSONResponse;
#end
and also set delegate to object of VedantViewControllerObject class as self in SecondViewController class and the object of VedantViewControllerObject class should be initialized and allocated.
vedantViewControllerObject.delegate = self;
In your VedantViewController.h file you declared method as below
-(void)displayAccounts:(NSString *)JSONResponse;
But you are calling it [delegate display:jsonResponse];
You just try to call
[delegate displayAccounts:jsonResponse];
And in SecondViewController.m
(void)displayAccounts:(NSString *)string{
}
There are some issues in your code:
set the delegate in second view controller
vedViewObject.delegate = self;
You added displayAccounts method in delegate and calling display method, that can cause issues. If that methods are not implemented in the delegate class.
Add if condition like: if(delegate)[delegate displayAccounts:jsonResponse];