Load UIViewController on another UIViewController in UIStoryboard from xib - iphone

I have a UIViewController(Say A). A separate nib file was loaded as popup on this view controller. When popup was closed by clicking a UIButton, I want to load another view controller(Say B) in UIStoryBoard. All the UIViewControllers were in storyboard.
I tried with delegates pattern. the delegate method returns self.storyboard as nil.
Please suggest how to handle (either performsegue from A to B or pushing new instance of B on navigation controller from nib file)
Here is code I used for delegate:
**In CustomViewNewPrescription.h file:**
#class CustomViewNewPrescription;
#protocol CustomViewNewPrescriptionDelegate <NSObject>
-(void)SaveCustomViewNewPrescription;
#end
#interface CustomViewNewPrescription : UIView{
id<CustomViewNewPrescriptionDelegate>delegate;
}
#property(nonatomic,strong) id<CustomViewNewPrescriptionDelegate>delegate;
**in .m:**
- (IBAction)btnCancel:(UIButton *)sender{
[self.delegate SaveCustomViewNewPrescription];
}
delegate was synthesized and initialised.
**In AddNewRx.h:**
#interface AddNewRx : UIViewController<CustomViewNewPrescriptionDelegate>{
}
**in AddNewRx.m:**
-(void)SaveCustomViewNewPrescription{
//either self performseguewithidentifier .... (or)
RxViewController *obj1 = [[self.navigationController storyboard] instantiateViewControllerWithIdentifier:#"RxViewController"];
[self.navigationController pushViewController:obj1 animated:YES];
}
In SaveCustomViewNewPrescription, self.storyboard giving nil values
Please suggest how to load another view controller in SaveCustomViewNewPrescription.

Instead of:
RxViewController *obj1 = [[self.navigationController storyboard] instantiateViewControllerWithIdentifier:#"RxViewController"];
Try:
UIStoryboard *yourStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
RxViewController *obj1 = [yourStoryboard instantiateViewControllerWithIdentifier:#"RxViewController"];

Related

Passing data between view controllers ios 7

I'm working on an app and I need to pass data between view controllers. I know this is a common question but I couldn't find an answer for my problem : I'm able to pass data from the FirstViewController (MasterViewController in my case) to the SecondViewController (SettingsViewController) but not the reverse. What happens is that I call a method from the FirstViewController in my SecondViewController.m file. This works and it logs the data. But when I quit the SecondViewController (using [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];) the data is reset.
I tried using other methods to pass data but it didn't work. I'm using this code to pass data:
MasterViewController *vc = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[vc setPorts:SelectedPorts];
I also tried replacing [vc setPorts:SelectedPorts]; with vc.selectedCellIndexes = SelectedPorts; but the same problem occurs.
the setPorts method is declared in the FirstViewController.h file and SelectedPorts is a variable I declared in SecondViewController.m (it's not nil I checked).
Here's the setPorts: in FirstViewController.m :
- (void) setPorts:(id)selectedPorts {
selectedCellIndexes = selectedPorts;
NSLog(#"selectedCellIndexes : %#", selectedCellIndexes);
}
This logs the good value but when I log it in viewWillAppear in FirstViewController.m it's reset to the value it has before I called the method from SecondViewController.m.
Just to clarify, if I DON'T quit the SecondViewController.m, the data isn't reset.
I did read all your comments, and I really thanks you for your help. for convenience, I used a global variable.
Thanks for your help.
You have a list of ports in MasterViewController and you expect to use it in the SettingsViewController.
The MasterViewController can hold this list and SettingsViewController should have an access to it.
In SettingsViewController, have a setSelectedPort method:
#property (nonatomic, retain) id selectedPorts
- (void) setPorts:(id)selectedPorts;
The method saves the selected ports list into a property.
In MasterViewController, call the SettingsViewController and give it the list.
SettingsViewController *vc = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
[vc setSelectedPorts:yourValue];
When the list is modified inside the SettingsViewController, the list of ports contained in MasterViewController won't move even if you leave the SettingsViewController.
In secondViewController, You create protocol
#import <UIKit/UIKit.h>
#protocol sampleDelegate <NSObject>
- (void)passValue:(id)selectedPorts
#end
#interface SecondViewController : UIViewController
#property (nonatomic, strong) id <sampleDelegate> passDelegate;
#end
In viewDidLoad or wherever method as per your need, call method like this,
[self.passDelegate passValue:selectedPorts];
In FirstViewController.h,
Import the delegate <sampleDelegate>,
#import "SecondViewController.h"
#interface FirstViewController : UIViewController<SampleDelegate>
#end
In FirstViewController.m,
-(void)passValue:(id)selectedPorts
{
id receivedValues = selectedPorts;
}
and set self in your SecondViewController allocation,
SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.passDelegate = self;
There is nothing unusual in the getting result. By doing
MasterViewController *vc = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[vc setPorts:SelectedPorts];
You are creating a new instance of MasterViewController from your SecondViewController. This is not the same from which you navigated to the SecondViewController. So you wont get the expected result. Since you are setting the ports([vc setPorts:SelectedPorts]) to the newly created instance of the Master.
Instead of creating a new instance,just hold the reference of the MasterViewController in SecondViewController in a property and assign it before moving to second VC. As a beginner I suggested this way. But using delegate is the prefferred way passing data back.
Either use delegate methods to communicate with the master VC from the modal VC, or you could do something like this if you want to retrieive some manipulated objects from the modal VC.
Set the object(s) as properties in the modal view controller's .h-file (so they are public).
Using unwind segues, in the master VC, just do this:
-(IBAction)exitModalVC:(UIStoryboardSegue*)segue
{
SomeObject *obj = ((YourModalVC*)segue.sourceViewController).someObject;
//Do what you want with obj
}
EDIT:
This will only work if you are using unwind segue (which is a neat way of dismissing modal VC when using story board)
And you are using this, which is not unwind segues:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
You were creating a new instance of the first view controller from the 2nd view controller not accessing the same instance of the original caller. That was the reason why while you could see the logs but data were not there when you got back to the original caller - your MasterViewController.
You need to use delegate method. Check my answer for this SO.
This is problem related to object ownership.
Follow the below steps:
As per understanding you want reverse value from "SecondViewController" to "FirstViewController"
Don't create new object of FirstViewController in SecondViewController, it will not work.
Create object of "FirstViewController" in "SecondViewController.h" file.
#property (nonatomic,strong) FirstViewController *firstViewController;
When you navigate from FirstViewController to SecondViewController, please pass the "self".
e.g. SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.firstViewController = self;
If you want pass the reverse value to FirstViewController then in SecondViewController.m file.
[self.firstViewController setPorts:SelectedPorts];
And in FirstViewController.m refresh your controls with latest values.
Try above code will defiantly work as per your requirement.

ECSliding, referece RightController in AppDelegate

I'm using ECSliding and I have this problem!
I have a topView and two menus,
left (LeftViewController)
right (RightViewController)
both UIViewController.
I want to give a reference to the right view controller, to the left view controller, in the AppDelegate.
I did in LeftViewController.h:
#import "RightViewController.h"
#class RightViewController;
#property (strong, monatomic) RightViewController *rightView;
in didFinishLaunchingWithOptions in AppDelegate.m :
RightViewController *rightViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Right"];
LeftViewController *leftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Left"];
leftViewController.rightView = rightViewController;
but I get this error in AppDelegate.m on self.storyboard:
Property 'storyboard not found on object of type 'AppDelegate *
How can I solve this problem?
Don't statically give them a reference to each other. Instead, when they are part of the sliding view controller self.slidingViewController will be a valid reference and you can navigate based on the relationships that actually exist:
self.slidingViewController.underLeftViewController
When using it, you should check the class and cast the reference:
LeftViewController *leftController = self.slidingViewController.underLeftViewController;
if ([leftController isKindOfClass:[LeftViewController class]]) {
leftController. ...;
}
First of all AppDelegate doesn't have a property storyboard it's a UIViewController property.
Second if you want to load the main storyboard and instantiate a view controller you should try the following:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"YourStoryboardName" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"YourViewController"];
Also make sure you properly set the view controllers identifier.

How to communicate with different view controller?

I have a VC that presents another VC modally. This 2nd VC pushes to a 3rd VC. The 3rd VC dismisses itself and needs to call a method on the initial VC. I can't seem to get this working. Any advice?
VC3 *aVC3 = [[self.navigationController.viewControllers objectAtIndex:0] parentViewController];
aVC3 = self.name;
[aVC3 addExercise];
[self dismissView];
Use delegate for backward messsaging.
Refer simple-delegate-tutorial-for-ios-development. Also refer the-basics-of-protocols-and-delegates
If you have UINavigationController there is no need of delegate to communicate to any viewController in navigationController like:
ViewController *objViewController = (ViewController *)[self.navigationController.viewControllers objectAtIndex:0]; //need to which controller u would like to communicate
[objViewController yourMethodHere]; // your method here
Here is an alternate method:
Step 1: Create a FirstViewController Property in the SecondViewController.h
#interface SecondaryViewController : UIViewController{
}
#property (nonatomic, strong) FirstViewController *viewControllerOne;
Step 2: set that property to self when presenting the SecondViewController in FirstViewController.m
#implementation SecondaryViewController
-(void)functionThatPresentsSecondViewController{
SecondViewController *viewControllerTwo = [[SecondViewController alloc] init];
[viewControllerTwo setViewControllerOne: self];
[self presentViewController:viewControllerTwo animated:NO completion:nil];
}
Step 3: You can now call FirstViewController functions from SecondViewController by using the viewControllerTwo.viewControllerOne property.

ViewController is loaded, but the view doesn't show up

I have a view whose controller is being instantiated (NSLog says so), but the view doesn't show up. If I load it as a modal view it appears, but not if I allocate it.
I have this structure (MenuView is the view that doesn't appear):
// ViewController.h
#import "MenuViewController.h"
#class MenuViewController;
#interface ViewController : UIViewController<ASIHTTPRequestDelegate>{
...
IBOutlet MenuViewController *menuView;
}
...
#property(nonatomic, retain) MenuViewController *menuView;
#end
// ViewController.m
#import "MenuViewController.h"
#implementation ViewController
#synthesize menuView;
- (void)loadMenu{
// THIS WORKS
// [self presentModalViewController:menuView animated:YES];
// THIS DOESN'T (VIEWCONTROLLER IS INSTANTIATED BUT VIEW DOESN'T APPEAR
menuView = [[[MenuViewController alloc] initWithNibName:#"MenuView" bundle:Nil] autorelease];
[self.navigationController pushViewController:menuView animated:YES];
}
Some ideas:
Try using self.menuView when assigning:
self.menuView = [[MenuViewController alloc] initWithNibName:#"MenuView" bundle:Nil];
Also, probably shouldn't autorelease a property. Release it in dealloc and set it to nil in viewDidUnload.
Make sure that self (ViewController) has a navigationController. Was ViewController pushed/presented by a navigationController?
Is - (void)loadMenu{ being called from the MainThread? Check with [NSThread mainThread]
Check out some tutorials/examples:
Adding a Navigation Controller by Hand
NavigationController Application in iPhone
Tutorial: Introducing UINavigationController Part 1
iPhone View Switching Tutorial

iPhone - pushViewController Issue

I have a root view controller which should load another view controller as soon as it is done loading (i.e. in the viewDidLoad method).
I am using the UINavigationController in order to push a new view controller onto the stack:
In my rootviewcontrollerappdelegate:
-(void) viewDidLoad{
LoginViewController* lvc = [[LoginViewController alloc]init];
[self.navigationController pushViewController:lvc animated:NO];
}
I have textfields and buttons in the view controller to be loaded. The above doesn't seem to work however...It loads just a blank grey screen and no UINavigation bar is present. If I comment out the second line (pushViewController line), then I see the navigation bar. So I think it is loading something, but the items in the view controller being loaded are not being shown...Any ideas why?
Check if navigationController is pointing to nil. If it does, try
[self.view addSubview:self.pushViewController.view]
I had the same problem and found the above solution here:
UIViewController -viewDidLoad not being called
Unless you're doing something tricky, you should be calling alloc on the LoginViewController class rather than a variable. Also, if you've set up LoginViewController in Interface Builder (as opposed to programmatically), you'll need to load it from an NIB:
LoginViewController *lvc = [[[LoginViewController alloc] initWithNibName:nil bundle:nil] autorelease];
[self.navigationController pushViewController:lvc animated:NO];
Have a look at initWithNibName:bundle: in the docs.
Not entirely sure what you are trying to achieve but when you instantiate LoginViewContoller it should probably look like this
LoginViewController* lvc = [[LoginViewController alloc]init];
Judging by the nature of your naming for your view controller, is your LoginViewController the first view controller for your UINavigationController?
If that is what you're trying to do, you should instead initialise your navigation controller with the LoginViewController as the root controller instead of pushing it onto the navigation stack.
UINavigationController has a method to do this:
- (id)initWithRootViewController:(UIViewController *)rootViewController
EDIT:
Well, one way you can go about it is like this.
In your application delegate .h file, you should have declared a UINavigationController.
#interface MyAppDelegate : NSObject <UIApplicationDelegate>
{
UINavigationController *navController;
}
#property (nonatomic, retain) UINavigationController *navController;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#end
In your App Delegate didFinishLaunching:withOption: you can create an instance of your LoginViewController there, and use that to init your UINavigation controller as the root view controller
#import "LoginViewController.h"
#implementation MyAppDelegate
#synthesize navController;
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
LoginViewController *loginController = [[LoginViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:loginController];
[loginController release];
[[self window] setRootViewController:navController];
[navController release];
[self.window makeKeyAndVisible];
return YES;
}
I probably have a typo here or there but that's one way I would go about doing it.