self.delegate is always nil - ios

I saw similar questions like this. In all the place they said to use className.delegate = self or other similar solutions. But i already checked i have did everything correctly. Then also i am facing self.delegate is nil problem.
I am trying to pass data from MyViewController to NextViewController on Button Click
I did,
1.Created Protocol in MyViewController
2.Created delegate Instance in MyViewController
3.Wrote this code in Button Click Event
-(void)buttnPressed:(id)s{
NextViewController* d=[[NextViewController alloc]init];
if(self.delegate){
NSLog(#"D");
}
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
[self.navigationController pushViewController:d animated:YES];
}
4.Implemented FirstViewController in NextViewController and set it's delegate
5.Created FirstViewController's instance (inside NextVC) and using that instance i set it's delegate as self
6.Implemented the delegate method in NextVC
I did everything correctly to my knowledge but i did not get the solution. Please help. Thanks for the time. (:
Here is my code
MyViewController.h
#import <UIKit/UIKit.h>
#protocol WatchListDelegate <NSObject>
-(void)groupSelected:(NSString *)grouDetails;
#end
#interface MyViewController : UIViewController
#property (strong,nonatomic) id<WatchListDelegate> delegate;
#end
MyViewController.m
#import "MyViewController.h"
#import "NextViewController.h"
#interface MyViewController ()
#property UIButton *buttonPopUp;
#end
#implementation MyViewController
-(id)init{
self = [super init];
return self;
}
-(void)loadView{
[super loadView];
self.buttonPopUp=[UIButton buttonWithType:UIButtonTypeCustom];
[self.buttonPopUp addTarget:self
action:#selector(buttnPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.buttonPopUp setTitle:#"Press ME" forState:UIControlStateNormal];
[self.buttonPopUp setBackgroundColor:[UIColor blueColor]];
self.buttonPopUp.frame=CGRectMake(80,180,80,40);
[self.view addSubview:self.buttonPopUp];
}
-(void)buttnPressed:(id)s{
if(self.delegate){
NSLog(#"D");
}
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
NextViewController* d=[[NextViewController alloc]init];
[self.navigationController pushViewController:d animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
#end
NextViewController.h
#import <UIKit/UIKit.h>
#import "MyViewController.h"
#interface NextViewController : UIViewController<WatchListDelegate>
#end
NextViewController.m
#import "NextViewController.h"
#interface NextViewController ()
#end
#implementation NextViewController
-(id)init{
self = [super init];
if(self){
MyViewController *m=[[MyViewController alloc]init];
m.delegate = self;
}
return self;
}
-(void)loadView{
[super loadView];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void)groupSelected:(NSString *)grouDetails{
NSLog(#"groupSelected");
}
#end
Thanks for the time (:

Try This:
-(void)buttnPressed:(id)s{
NextViewController* d= [self.storyboard instantiateViewControllerWithIdentifier:#"VCidentiferFromStoryBoard"];
self.delegate = d;
[self.navigationController pushViewController:d animated:YES];
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
}

I don't think you need a delegate to pass data, you're trying to pass the string value 'df'? If so you could just create a public property in NextViewController and assign it a value when you create NextViewController in MyViewController?
The delegate is nil, because it does not look like you set it, so in the button pressed logic you would do self.delegate = d;, don't assign the delegate or create MyViewController in the init of NextViewController, then check the delegate and it won't be nil, but I don't think you need the delegate pattern in this case?
Let me know if you need me to clarify or there is something else in particular you need to pass.

Edit your MyViewController.m
#implementation MyViewController
{
NextViewController* nextViewController;
}
Then rewrite the buttnPressed method like below:
-(void)buttnPressed:(id)s
{
if(!nextViewController) // this way only one time NextVC will be created
{
nextViewController = [[NextViewController alloc]init];
[self.navigationController pushViewController:nextViewController animated:YES];
self.delegate = nextViewController;
}
if (self.delegate && [self.delegate respondsToSelector:#selector(groupSelected:)]) {
[self.delegate groupSelected:#"df"];
}
}

Related

How to call delegate when VC is dismissed?

I have two VC. I need to call the delegate function when the 2nd VC is dismissed.
In my 1st VC or main VC I have given the following code in .h file.
#interface FirstVC : ....<SecondVCDelegate>
-(void)didDismissViewController:(UIViewController*)vc;
But for some reason SecondVCDelegate in this is not detected.
while presenting 2nd VC from first I have given this .m file of 1st VC.
SecondVC *optionsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
optionsVC.delegate = self;
optionsVC.view.backgroundColor = [UIColor blackColor];
optionsVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:optionsVC animated:YES completion:^{}];
in 2nd VC .h file
#protocol SecondVCDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
#end
#interface SecondVC : ...
#property (nonatomic) id<SecondVCDelegate> delegate;
#end
in 2nd VC .m file I have dismissed using the below code
[self dismissViewControllerAnimated:YES completion:nil];
Could you point out what I did wrong with possible explanation. Thanks in advance.
This is the working code on xcode 9 :
ViewController.m :
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController () <SecondVCDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)action:(id)sender {
SecondViewController *optionsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
optionsVC.delegate = self;
optionsVC.view.backgroundColor = [UIColor blackColor];
optionsVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:optionsVC animated:YES completion:nil];
}
-(void) didDismissViewController:(UIViewController *)vc{
NSLog(#"working controller : %#", vc);
}
#end
SecondViewController.h :
#import <UIKit/UIKit.h>
#protocol SecondVCDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id<SecondVCDelegate> delegate;
#end
SecondViewController.m :
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)didmissAction:(id)sender {
[self dismissViewControllerAnimated:true completion:^{
[_delegate didDismissViewController:self];
}];
}
#end
On your 2nd VC .m do like this
First synthesize delegate below implementation
#synthesize delegate;
after that use it on viewController dismiss:
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController: self];
}];

Custom Delegate method is not getting called

I have set up custom delegate as follows, but delegate method is not getting called. I wonder what I am missing in my following implementation.
ComboSetViewController.h
#protocol ComboSetViewControllerDelegate <NSObject>
#required
- (void)comboSelected;
#end
#interface ComboViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, weak) id <ComboSetViewControllerDelegate> comboSelectedDelegate;
#end
ComboSetViewController.m
- (IBAction)doneBtnClicked
{
selectedCombo.orderProductItemArray = comboOrderItemArray;
[comboSelectedDelegate comboSelected];
[self dismissViewControllerAnimated:YES completion:nil];
}
HomeViewController.h
#import "ComboViewController.h"
#interface HomeViewController : UIViewController<ComboSetViewControllerDelegate>
HomeViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
ComboViewController *comboViewController = [[ComboViewController alloc] init];
comboViewController.comboSelectedDelegate = self;
}
// is not getting called
-(void)comboSelected
{
NSLog(#"Combo Selected");
}
EDIT: If I assign the delegate in the prepareSegue, then it works.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"isCombo"])
{
ComboViewController *vc = [segue destinationViewController];
// Assign self as the delegate for the child view controller
vc.comboSelectedDelegate = self;
}
}

ContainerViewController delegate to ChildViewController

ContainerViewController delegate the method -delegateMethod to ChildViewController.
But in the following code, -delegateMethod is not called.
I think it's because _childViewController has been released.
How do I fix it to make run -delegateMethod?
ContainerViewController.h
#protocol ContainerViewDelegate <NSObject>
- (void)delegateMethod;
#end
#interface ContainerViewController : UIViewController
#property (nonatomic, assign) id<ContainerViewDelegate> delegate;
#end
ContainerViewController.m
#interface ContainerViewController () {
ChildViewController *_childViewController;
}
//...
- (void)viewDidLoad
{
_childViewController = [[WeeklyViewController alloc]init];
[self addChildViewController:_childViewController];
[self.view addSubview:_childViewController.view];
[_childViewController didMoveToParentViewController:self];
}
- (void)buttonAction {
[self.delegate delegateMethod];
}
ChildViewController.m
#interface ChildViewController () <ContainerViewDelegate>
//...
- (void)delegateMethod {
NSLog(#"succeed!");
}
You never set the delegate, so self.delegate will be nil. You should do this,
- (void)viewDidLoad
{
_childViewController = [[WeeklyViewController alloc]init];
self.delegate = _childViewController;
[self addChildViewController:_childViewController];
[self.view addSubview:_childViewController.view];
[_childViewController didMoveToParentViewController:self];
}

respondsToSelector Cannot be Called?

Sorry about the confusion.
What I want to do:
enter a string in a textfield in a view(EnterCommandViewController) and click save button, which will dismiss current view and go back to another view(DetectionViewController) and show the string in the UILabel in current view(DetectionViewController). So I have put define the delegate protocol in EnterCommandViewController, my question is that why the respondToSelector, which is used to check whether someone is listening does not work.
I am really a beginner in iOS, I am right now writing a delegate to send text got form UITextField to a UILabel, But I found that the respondToSelector cannot be called by using NSLog for testing.
Below is my code for reference:
EnterCommandViewController.h
#import <UIKit/UIKit.h>
#import "RscMgr.h"
#protocol EnterCommandDelegate <NSObject>
-(void) commandEntered:(NSString*)command;
#end
#interface EnterCommandViewController : UIViewController <RscMgrDelegate>
{
RscMgr* rscMgr;
__weak IBOutlet UITextField *inputTextField;
__unsafe_unretained id<EnterCommandDelegate> delegate;
}
-(void)sendMessage:(NSString*)message;
- (IBAction)cancelPressed;
- (IBAction)savePressed;
#property (nonatomic,assign)id delegate;
#end
EnterCommandViewController.m
#import "EnterCommandViewController.h"
#interface EnterCommandViewController () <UITextFieldDelegate>
{
#private
BOOL connected;
}
#end
#implementation EnterCommandViewController
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
rscMgr = [[RscMgr alloc] init];
[rscMgr setDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
inputTextField.text=#"";
[inputTextField becomeFirstResponder];
}
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputTextField.delegate = self;
}
-(void) viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
inputTextField.delegate = nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cancelPressed {
[self dismissViewControllerAnimated:YES completion:^{}];
}
- (IBAction)savePressed {
//is anyone listening
NSLog(#"the command is %#",inputTextField.text);
NSLog(#"Checking -- SomeMethod is listening");
if([delegate respondsToSelector:#selector(commandEntered:)]){
NSLog(#"SomeMethod is listening");
//send delegate function with the command entered by the user
[delegate commandEntered:inputTextField.text];
}
[self dismissViewControllerAnimated:YES completion:^{}];
}
DetectionViewController.h
#import <UIKit/UIKit.h>
#import "EnterCommandViewController.h"
#interface DetectionViewController : UIViewController <EnterCommandDelegate>{
__weak IBOutlet UILabel *showCommand;
}
- (IBAction)showSettings:(UIBarButtonItem *)sender;
#end
DetectionViewController.m
#import <Foundation/Foundation.h>
#import "DetectionViewController.h"
#implementation DetectionViewController
- (IBAction)showSettings:(UIBarButtonItem *)sender {
}
-(void) viewDidLoad{
[super viewDidLoad];
showCommand.text=#"";
EnterCommandViewController* enterCVC = [[EnterCommandViewController alloc] init];
enterCVC.delegate = self;
}
#pragma mark - EnterCommandDelegate function(s)
-(void) commandEntered:(NSString *)command{
// showCommand.text = command;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"command: %#",command);
[self->showCommand setText:command];
});
}
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
You are not setting the delegate properly.
EnterCommandViewController* enterCVC = [[EnterCommandViewController alloc] init];
enterCVC.delegate = self;
This is not the way of setting the delegate in your case, since you are not using the created instance of enterCVC, instead a new instance is created from the storyboard when you are transitioning toEnterCommandViewController `(From your comment its clear that you are using the storyboard for this).
So what you can do is you should the delegate from prepareForSegue in DetectionViewController like
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get reference to the destination view controller
EnterCommandViewController* enterCVC = [segue destinationViewController];
enterCVC.delegate = self;
}

Cannot reference delegate protocols in implimentation

I have a UIViewController with a UIPickerView that creates a string that I want to pass along to my RootViewController (BL_MainViewController).
My tactic was to use the delegate pattern but I can't figure out where I'm going wrong here. If my RootViewController is created using a Storyboard, how do I tell it BL_MainViewController.BL_SetTimerViewController = self and where do I set that in the implementation (guess:ViewDidLoad)?
BL_SetTimerViewController.h (the child VC presented by modal segue in IB)
#protocol BL_SetTimerViewControllerDelegate
-(void) updateLabelWithString:(NSString *)string;
#end
#interface BL_SetTimerViewController : UIViewController{
... // some ivars
}
#property (assign, nonatomic) id <BL_SetTimerViewControllerDelegate> delegate;
#end
BL_SetTimerViewController.m
#implementation BL_SetTimerViewController
...
#synthesize delegate;
...
- (IBAction)setTimerAndDismissViewController:(id)sender {
// does some stuff, then:
[self.delegate updateLabelWithString:#"TEST"];
[self dismissViewControllerAnimated:YES completion:nil];
}
BL_MainViewController.h (The Root VC)
#import "BL_SetTimerViewController.h"
#interface BL_MainViewController : UIViewController <BL_SetTimerViewControllerDelegate>{
...
}
#end
BL_MainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// do some stuff here
// presumably also assign the delegate protocol?
}
-(void)updateLabelWithString:(NSString *)string {
self.pLabel.text = string;
}
In your BL_MainViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.pLabel.text=GlobleSting;
}
-(void)updateLabelWithString:(NSString *)string {
GlobleSting = string; //declare in .h file
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"YoursegueIdentifir"]) {
BL_SetTimerViewController *settimerVC =
segue.destinationViewController;
settimerVC.delegate = self;
}
}
Super simple test app for delegate(note that many thing are left out as it's quickly thrown together), this works for me.(note that delegate is weak, not assign. If you are targeting iOS 5+, use weak for delegates)
SimpleProtocol.h
#protocol SimpleProtocol <NSObject>
- (void)updateText:(NSString *)text;
#end
ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#import "SimpleProtocol.h"
#interface ViewController ()<SimpleProtocol>
#property (nonatomic, weak) IBOutlet UILabel *label;
#end
#implementation ViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SecondViewController *vc = (SecondViewController *)segue.destinationViewController;
vc.delegate = self;
}
- (void)updateText:(NSString *)text
{
self.label.text = text;
}
#end
SecondViewController.m
#import "SimpleProtocol.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:#selector(timerFire:) userInfo:nil repeats:NO];
}
- (void)timerFire:(NSTimer *)timer
{
NSString *text = [NSString stringWithFormat:#"Test %#", #(arc4random())];
[self.delegate updateText:text];
[self.navigationController popViewControllerAnimated:YES];
}
#end

Resources