ContainerViewController delegate to ChildViewController - ios

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];
}

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;
}
}

self.delegate is always nil

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"];
}
}

Dissmis NavigationViewController never dealloc the rootViewController

I am trying to show a modal view controller(view1) inside another viewController(view2)
View1
#interface View1 : UIViewController
#property (weak) id delegate;
- (IBAction)closeButtonTapped:(id)sender ;
#end
#protocol View1Delegates <NSObject>
#optional
- (void)viewControllerDidFinish: (View1 *) viewController;
#end
#implementation View1
-(void)dealloc
{
}
- (void)viewDidLoad {
}
- (IBAction)closeButtonTapped:(id)sender {
[self.delegate viewControllerDidFinish:self];
}
#end
And I use the following code inside view2
#implementation View2
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)onOpenView1Tapped:(id)sender
{
View1 *view1 = [self.storyboard instantiateViewControllerWithIdentifier:#"view1"];
NavViewController *nav = [[NavViewController alloc] initWithRootViewController:view1];
view1.delegate = self;
[self presentViewController:nav animated:NO completion:NULL];
}
- (void) viewControllerDidFinish: (View1 *) viewController
{
[self dismissViewControllerAnimated:NO completion:NULL];
}
The problem is that the NavViewController calls its dealloc method but view1 never calls it at all after dismiss. This means that view1 will remains in memory .
How can I free the memory of view1 ?

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