How to get the parentViewController in childViewController? - ios

I have a main UIViewController and named AddInformationController. In this mainViewController I have two UIContainerView. Each of them embed with a UITableViewController. The table view controllers are named InformationSegmentController and ResultSegmentController.
I put this in AddInformationController:
InformationSegmentController *isc = [self.storyboard instantiateViewControllerWithIdentfier:#"InformationSegmentController"];
ResultSegmentController *rsc = [self.storyboard instantiateViewControllerWithIdentifier: #"ResultSegmentController"];
[self addChildViewController: isc];
[self addChildViewController: rsc];
In either the InformationSegmentController class or ResultSegmentController class, I tried to Log this:
NSLog(#"%#",self.parentViewController);
But unfortunately, it is a nil. How can I get the parentViewController correctly? Do I have to use the prepareForSegue?
// Question Update:
I found that I don't have to call addChildViewController method again if I create those childViewControllers directly in my storyboard.
I have tried to NSLog(#"%#", self.childViewControllers) in my AddInformationController and the result contains InformationSegmentController class and ResultSegmentController class.
But the problem is when I call NSLog(#"%#", self.parentViewController) on both childViewContorllers in viewDidLoad, the results is nil.

You have to try like this
//add childview
[self addChildViewController:aVC];
[self.view addSubview:aVC.view];
[aVC didMoveToParentViewController:self];
//remove
[self removeFromParentViewController];
[self didMoveToParentViewController:nil];
[self.view removeFromSuperview];
Hope it Helps you.
OR
another way to get PerentViewController in ChildViewControler is Make #property (strong, nonatomic) AddInformationController *ParentVC; in Your ChildViewController.h and assign viewController from your ParentViewController Like
InformationSegmentController *isc = [self.storyboard instantiateViewControllerWithIdentfier:#"InformationSegmentController"];
isc.ParentVC = self;
[self addChildViewController: isc];

Give identifiers to both the segues to your container views(suppose "InformationSegmentControllerSegue" and "ResultSegmentControllerSegue" ,namely) and use prepareForSegue in your AddInformationController like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"InformationSegmentControllerSegue"]) {
InformationSegmentController *container1 = segue.destinationViewController;
}
else if([[segue identifier] isEqualToString:#"ResultSegmentControllerSegue"]) {
ResultSegmentController *container2 = segue.destinationViewController;
}
}
Hope this helps you.

Related

protocol method is not being called by the delegate

I have implemented protocol in my app,
I have declared protocol method in loginViewController and i am calling protocolMethod from confirmViewController
Here is my code snippet:
loginViewController.h
#protocol FirstControllerDelegate<NSObject>
#required
-(void)protocolMethod;
#end
#interface loginViewController : UIViewController<FirstControllerDelegate>
#end
loginViewController.m
- (IBAction)loginBtnClicked:(id)sender {
confirmViewController *obj = [confirmViewController new];
obj.delegate=self;
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
}
-(void)protocolMethod{
NSLog(#"--- This is not callled ---");
[self dismissViewControllerAnimated:NO completion:nil];
}
Code for
confirmViewController.h
#interface confirmViewController : UIViewController
#property (nonatomic, assign) id <FirstControllerDelegate> delegate;
#end
confirmViewController.m
(IBAction)continueClicked:(id)sender {
[_delegate protocolMethod]; //Calling protocol method...
[self dismissViewControllerAnimated:YES completion:nil];
}
Where i am doing mistake?
Please help and thanks in advance!
Wrong Approach and delegate initialisation
In this lines:-
confirmViewController *obj = [confirmViewController new];
obj.delegate=self;
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
--- You are loosing the object here
Solution
In your attribute inspector give the identifier for that confirmViewController, now push the vc and set the delegate for the object confirmViewController like this:-
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ConfirmViewController *confirmViewController = [storyboard instantiateViewControllerWithIdentifier:#"ConfirmViewController"];
confirmViewController.delegate=self;
[self.navigationController pushViewController:confirmViewController animated:YES];
The delegating class does not exist for long enough to matter:
- (IBAction)loginBtnClicked:(id)sender {
confirmViewController *obj = [confirmViewController new];
obj.delegate=self;
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
// obj is destroyed here
}
You need to implement prepareForSegue and set delegate there e.g.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
confirmViewController *destViewController = (confirmViewController *)segue.destinationViewController;
destViewController.delegate=self;
}
for further detail check this link:- http://www.appcoda.com/storyboards-ios-tutorial-pass-data-between-view-controller-with-segue/
You have to set delegate there. please,make some correction in your code like:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
confirmViewController *destViewController = (confirmViewController *)segue.destinationViewController;
destViewController.delegate=self;
}
You shoul use preparefrosegue to set your delegate object. so your code should be like this,
- (IBAction)loginBtnClicked:(id)sender {
[self performSegueWithIdentifier:#"confirmloginsegue" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
confirmViewController *obj = [confirmViewController new];
//or
confirmViewController *obj = [segue destinationViewController];
obj.delegate=self;
}
hope this will help ;)
If u are using View controller
SettingsHubViewController *settingVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"yourStoryBoardIdentifier"];
settingVC.delegate = self;
If u are using XIB load the NIB after that set the settingVC.delegate = self;
its working for me (I created OverLay view and loaded in main class)

Unable to pass data between MasterVC to DetailVC in iOS

I'm trying to pass data(_claimReportToDetailView) from viewDidLoad (of MasterVC) to DetailVC. It's always null.
#interface LAMasterViewController ()
{
NSArray *_claimReports;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_claimReports = [[LADataModelController getSingleton] getClaimReportsOrderedByAccessedDate];
LADetailViewController *detailViewController = [[LADetailViewController alloc] init];
detailViewController.claimReportToDetailView = (LAClaimReport *)_claimReports[0];
NSLog(#"claim%#",detailViewController.claimReportToDetailView); // captures here properly.
}
#interface LADetailViewController : UIViewController
#property(nonatomic ) LAClaimReport *claimReportToDetailView;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"sdfdf%#", _claimReportToDetailView); // logs null always.
}
Your viewDidLoad seems strange. You have this line:
LADetailViewController *detailViewController = [[LADetailViewController alloc]init];
Yet you say that the view controller is on the storyboard.
I think what is happening is that you are creating this VC, and setting it's property, but the Storyboard is loading a completely new VC, for which you haven't set the property.
Usually, the way you pass information to VCs on Storyboards is in the prepareForSegue: method.
You have to pass the data to the details view controller in prepareForSeque method in master view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) { //<-make shire the segue identifier match one in storyboard
_claimReports = [[LADataModelController getSingleton] getClaimReportsOrderedByAccessedDate] ;
LADetailViewController *vc = (LADetailViewController*)[sender destinationViewController];
vc.claimReportToDetailView = (LAClaimReport *)_claimReports[0];
}
}
This should fix your project. Give it a try
//Allocating LADetailViewController instance
LADetailViewController *detailViewController = [[LADetailViewController alloc]init];
//Connecting it the specified VC on storyboard
detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"yourVCID"];
//Now the connection is set, so pass the data you need
detailViewController.claimReportToDetailView = (LAClaimReport *)_claimReports[0];
//Depending on present or push you should try one of the 2 lines
[self.navigationController pushViewController:detailViewController animated:YES];
//or
[self presentViewController:detailViewController animated:YES completion:nil];
This happens because whenever you navigate from one UIViewController to other, it is initialized again, so rather than setting value in viewDidLoad, try to set value on the event when you perform navigation and make navigation through code rather than with segue.

IOS7 Change value of label in different view before segue (Same controller)

I have 2 simple views in my Storyboard and both use the same ViewController. I have the following code to switch the the second view...
self.labelStatus.text = #"CHECKING";
[self performSegueWithIdentifier:#"LoginSuccess" sender:sender];
*labelStatus is on the second view.
For some reason the labels text is not changing. Can anyone advise why this is?
[self performSegueWithIdentifier:#"LoginSuccess" sender:sender];
//change the label value in prepareForSegue: method
- (void)prepareForSegue:(UIStoryboardSegue *)segue {
if ([segue.identifier isEqualToString:#"LoginSuccess"]) {
UIViewController *loginVC = segue.destinationViewController;
//declare the string in .h file and assign it in viewDidLoad in loginVC
loginVC.labelString = #"CHECKING";
}
}
in loginViewController.h file
#property(nonatomic, strong) NSString *labelString;
in loginViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.labelStatus.text = labelString
}
You can customise your destinationViewController (properties, views, etc) in prepareForSegue: method, which is called before segue is executed:
- (void)prepareForSegue:(UISegue *)segue {
if ([segue.identifier isEqualToString:#"mySegue"]) {
UIViewController *destVC = segue.destinationViewController;
// do your customisation
}
}
Edit-
If you need to change the label in the same view controller, then you should modify the label in the prepareForSegue method.

Objective C block property is always nil

I'm trying to learn more about Objective C blocks and how they work. I've set up a simple project with two UIViewControllers embedded in a UINavigationController in Storyboard. I'm attempting to change the background color of the first ViewController's view from the second view controller. Here's some code:
ViewController.m
#implementation ViewController{
ColorBlock _colorBlock;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"theSegue"]){
SecondViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.colorBlock = _colorBlock;
}
}
- (IBAction)moveToSecondViewController:(id)sender {
__weak id weakSelf = self;
_colorBlock = ^{
[[weakSelf view] setBackgroundColor:[UIColor redColor]];
};
}
SecondViewController.h
typedef void (^ColorBlock)(void);
#interface SecondViewController : UIViewController
#property (readwrite, copy) ColorBlock colorBlock;
#end
SecondViewController.m
- (IBAction)buttonTapped:(id)sender {
if(self.colorBlock){
self.colorBlock();
}
}
The first ViewController's background color isn't being changed because in the buttonTapped: method of SecondViewController.m, self.colorBlock is nil, causing the block invocation not to be called. I thought I had successfully set the block in prepareForSegue:sender:. Why is my block property nil?
In your prepareForSegue, the destination has already been instantiated. So assuming that SecondViewController is the destination, you can do:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"theSegue"]){
SecondViewController *vc = segue.destinationViewController;
NSAssert([vc isKindOfClass:[SecondViewController class]], #"destination is not SecondViewController class");
vc.colorBlock = _colorBlock;
}
}

In storyboard, Popoverview don't receive delegation

I'm working sample app by storyboard.
When made popoverview, I used the way - 'Embed in navigation controller'.
But I'm getting a big trouble of delegate usage.
It's that don't delegate to popover view's.
[ViweController.m]
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"PopRootViewController"]){
NSLog(#"[segue destinationViewController] :%#", [segue destinationViewController]);
rootViewController = [[RootViewController alloc] init];
rootViewController.delegate = (id)self;
NSLog(#"%#---%#---%#", rootViewController.delegate, self, rootViewController);
}
}
-(void)didTap22 {
NSLog(#"delegate step 1 success!! ");
}
The result of this source like this :
[segue destinationViewController] :<UINavigationController: 0x88660a0>
<ViewController: 0x6b795e0>---<ViewController: 0x6b795e0>---<RootViewController: 0x6b7da60>
but [RootViewController] don't receive the delegation.
[RootViewController.m]
#implementation RootViewController
#synthesize items, delegate;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
....
self.items = mutableFetchResults;
NSLog(#"333333..... %#, ....... %#", self.delegate, self);
}
results :
333333..... (null), ....... <RootViewController: 0x8866520>
RootViewController's delegation is null.
I can't find solution about this.
Anybody help me, please!
I suspect you didn't declare your delegate UIPopoverControllerDelegate in the class declaration of your view controller.
This line is suspicious:
rootViewController.delegate = (id)self;
you don't need to cast self normally if you made the declaration I am mentioning.

Resources