I want to test a function of a ViewController that changes a label.text.
At first I tried this:
ViewController* controller = [[ViewControlleralloc] initWithNibName:#"ViewController_iPhone"bundle:nil];
[controller pressed];
NSLog(#"%#",controller.label.text);
the function pressed is below:
-(void)pressed{
self.label.text = #"hello";
}
however, the result is NULL.
Later I changed code as followed:
AppDelegate *delegate = [[UIApplicationsharedApplication] delegate];
ViewController* controller = [[ViewControlleralloc] initWithNibName:#"ViewController_iPhone"bundle:nil];
delegate.window.rootViewController = controller;
[controller pressed];
NSLog(#"%#",controller.label.text);
I think this code
delegate.window.rootViewController = controller;
can load the controller's view so that the label's text can be changed.But I don't know why.
You are correct.
A view isn't loaded until it is needed. Simply creating a view controller doesn't trigger view loading but assigning the window's root view controller requires it to be set up for display and therefore instantiates and links all the nib objects.
Any reference to the view would also have caused it to load, even something like:
ViewController* controller = [[ViewControlleralloc] initWithNibName:#"ViewController_iPhone"bundle:nil];
NSLog(#"%#", controller.view);
Related
I have been working on this problem for a while and thought I would ask for some help. I have 3 view-controllers: 1 Navigation Controller, 1 Main controller and 1 detail view controller.
Within the main view controller, I have a series of subviews with buttons. Due to the class structure, however, I am unable to directly call self.storyboard to get the current storyboard object.
I have tried 2 different methods, a variety of ways, and am still unsuccessful. I posted my methods below and described what is and what is not happening in each segment. The overall goal is to present a child view controller (the detail view) by tapping a button in a subview, of which does not have access to the parent storyboard directly.
Method 1
//Instantiate the new view controller
ProfileViewViewController *tempViewToShow = [del.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"profile"];
// Pass data into the new view controller
tempViewToShow.thisUser = self.postUser;
// Output a simple log to ensure both were created
NSLog(#"Temp User Name: %#, Profile Desc: %#", [tempViewToShow.thisUser getFullName], tempViewToShow.description);
// Using the AppDelegate for the RootViewController, present the detail view
[UIApplication.sharedApplication.delegate.window.rootViewController presentViewController:tempViewToShow animated:YES completion:NULL];
Issues
The issue with this series is that the detail view does not carry the navigation controller (since it is not mentioned), however, this way still shows a full View Controller
Method 2
...
// Use the Delegate and the navigation controller to present the new view controller
[UIApplication.sharedApplication.delegate.window.rootViewController.navigationController presentViewController:tempViewToShow animated:YES completion:NULL];
Issues
Does not display anything
Method 3
// Use the recommended 'pushViewController' for the navigation controller to carry over
[UIApplication.sharedApplication.delegate.window.rootViewController.navigationController pushViewController:tempViewToShow animated:NO];
Issues
Does not display anything
En toto, how would I make this work? What lines would I modify and how? Thanks!
You can solve this issue like this:
ProfileViewViewController *tempViewToShow = [del.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"profile"];
UINavigationController *naviController = [[UINavigationController alloc] tempViewToShow];
And then do this :
[UIApplication.sharedApplication.delegate.window.rootViewController presentViewController:naviController animated:YES completion:NULL];
You can create instance of storyboard from storyboard name.once you have correct storyboard instance, get NavigationController from Its identifier, and detailviewController from its identifier. Push detailviewcontroller on Navigationviewcontroller.
get storyboard-- replace name of your storyboard in "MainSToryboard"
UIStoryboard *storyboard =
[UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:[NSBundle mainBundle]];
get instance of Navigationcontroller - replace identifier:
UINavigationController *navController =(UINavigationController *)
[storyboard instantiateViewControllerWithIdentifier:#"navcontroller"];
get detailviewconrtoller :
UIViewController *detailvc=
[storyboard instantiateViewControllerWithIdentifier:#"profile"];
Push detail on current navigationcontroller:
[navController pushViewController:detailvc animated:YES];
I found an alternate solution. The cause was because the incorrect view controller was being called by
UIApplication.sharedApplication.delegate.window.rootViewController.*
The workaround is:
In the primary view controller class, I passed the displayed viewcontroller into the delegate class. Then, from the child class I wanted to call, I referenced that view controller, and navigation controller, and it worked just fine. My final code is below:
// Create the detail View Controller
ProfileViewViewController *tempViewToShow = [del.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"profile"];
// Set the user variable in the detail view controller
tempViewToShow.thisUser = self.postUser;
// Push the view controller into the navigation controller
// Note that del.currentNav comes from this code:
/*
* In this class, create the delegate reference
* AppDelegate *del = (AppDelegate *)[[UIApplication sharedApplication] delegate]
*
* In the Delegate class, get the set the current navigation controller {let currentVC : UIViewController = passedInVC}
* self.currentNav = currentVC.navigationController;
*/
[del.currentNav pushViewController:tempViewToShow animated:YES];
I have two views in the Tab Bar View. I want my second view to inform first view, when its Text Fields have changed value. I've done all the necessary coding for it, but there is one problem - first view doesn't see connected label outlets in the method declaration.
Code of the second view:
- (IBAction)textFieldHasChanged:(UITextField *)sender {
id<HPAAddCarOverallInfoTVCDelegate> strongDelegate = [[HPAAddCarMainViewController alloc] init];
if([strongDelegate respondsToSelector:#selector(addCarOverallInfoVC:textFieldValueChanged:)]) {
[strongDelegate addCarOverallInfoVC:self textFieldValueChanged:sender.text];
}
}
Code of the first view:
-(void)addCarOverallInfoVC:(HPAAddCarOverallInfoTableViewController *)viewController textFieldValueChanged:(NSString *)value
{
self.overallVCFieldCount.text = value;
NSLog(#"%#", value);
}
self.overallVCFieldCount.text = value; - value exist, but textField doesn't.
As I think, problem belongs at this line of code:
id<HPAAddCarOverallInfoTVCDelegate> strongDelegate = [[HPAAddCarMainViewController alloc] init];
I guess, that delegate isn't exact view with which I am working with. Bouth views are loaded at the same time via storyboard. If I am correct with my thought, can you tell me please, how can I give a pointer to exact first view which as second view are loaded when Tab Bar View controller goes on the screen?
You're creating a new view controller in textFieldHasChanged. If you have that view controller in IB, instantiate it like this:
UIStoryboard *st = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:#"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
id<HPAAddCarOverallInfoTVCDelegate> strongDelegate = st instantiateViewControllerWithIdentifier:#"identifier"];
Where identifier is the identifier you have given your view controller in your storyboard.
I've made a tabbar controller with two views (standard setup from the template). First view is accessing an array within an dataController object. When I tap to the second view on the tabbar, I want the dataController reference to be set on the second viewController's dataController property.
I use call
SecondViewController *vc = [[self storyboard] instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc.dataController = self.dataController;
However, when I call my countArrayObjects on the secondViewController's dataController property, I always get 0 back - eventhough there should be objects in the array and I can't figure out why?
I've set the identifier on the secondViewController in MainStoryBoard and I have no crashes, the property just isn't set (I think).
For testing purposes I call the instantiateViewControllerWithIdentifier from a simple button, before tapping on to the secondView. And I call the countArrayObjects from viewDidLoad on secondViewController.
Any ideas?
Hmmm... I was having the same problem. At the moment, the only way I got around this is to test for the views superview being nil - which as its accessing the view selector of the class fires up the view did load event...
both of us are doing something wrong here though...
This is the test code I wrote...
SummaryViewController *sc = [self.childViewControllers objectAtIndex:0];
if(sc.view.superview == nil) sc.checkInTime.alpha = 0;
//-- by inspecting the value, it will call the viewDidLoad method of the controller.
It works, but it's wrong.
When I try to push a UIViewController subclass (MissionViewController) onto a UINavigationController from within my root view controller, the viewDidLoad method is only called if I reference the underlying view after initializing the view controller. However, even with the method called, the screen is not updated.
Both the view controller and the navigation controller are not nil. The file owner in MissionView.xib is set to MissionViewController. The view property of the file owner points to the nib view. I've verified that the topViewController property of the navigation controller points to the MissionViewController object.
If I change MissionViewController to be the root view controller, the view loads fine. Saw several similar posts but still having problems.
rootViewController.h
#interface TreeGraphController : UIViewController
{
MissionViewController *missionViewCtrlr;
}
#property(nonatomic, retain) MissionViewController *missionViewCtrlr;
rootViewController.m
#import "MissionViewController.h"
...
if (!missionViewCtrlr)
{
MissionViewController *ctrlr = [[MissionViewController alloc] initWithNibName:#"MissionView" bundle:nil];
ctrlr.view.hidden = NO;
self.missionViewCtrlr = ctrlr;
[ctrlr release];
}
myAppDelegate *del = [[UIApplication sharedApplication] delegate];
[del.navigationController pushViewController:missionViewCtrlr animated:NO];
What about using
[self.navigationController pushViewController:missionViewCtrlr];
in the rootViewController? I assume rootViewController has been pushed to a UINavigationController and that the navigation controller's view was added as a subview of self.window in the app delegate?
Btw, you may simplify part of your code by just saying
if(!missionViewCtrlr)
self.missionViewCtrlr = [[MisionViewController alloc] init...];
I'm looking to find out how to switch to a UISplitView from another view. The user will click on a button and the Split View should open. I'm having no luck at all.
I start with a normal view and when the user clicks on the button i try to switch to the split view by removing the current view and initing the split view controller. I would just use a nib to load it but split views don't have nib files.
Is there anyone that can get me the simplest way to do this.
You have to create the UISplitViewController programatically. You have to give it an array of two UIViewController objects (these can be from nib files). Then when you want to load the split view you send the message [window addSubView:splitViewController.view]
i have practically done something like this.
i declared a SplitViewController in viewDidLoad at one of my viewcontroller (FrameViewController)
Then i added the splitViewController that i have just declared into AppDelegate's window variable. (i have tried declaring another UIWindow variable and add SplitViewController's view to it, it will throw wait_fences: failed to receive reply: 10004003 when u change orientation)
then, set your viewController's view to hidden so that the SplitViewController will be displayed correctly..
Voila~
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (iPadProject2AppDelegate *)[[UIApplication sharedApplication] delegate];
ContentViewController* secondVC = [[ContentViewController alloc]
initWithNibName:#"ContentView" bundle:nil];
MenuViewController* firstVC = [[MenuViewController alloc]
initWithNibName:#"MenuView"
bundle:nil
withContentViewController:secondVC];
UISplitViewController* splitVC = [[UISplitViewController alloc] init];
splitVC.viewControllers = [NSArray arrayWithObjects:firstVC, secondVC, nil];
[appDelegate.window addSubview:splitVC.view];
[self.view setHidden:YES];}
BTW,
you should add these code into Yit Ming's code:
[[self view] removeFromSuperview];
Or the Split View will not work while you change the orientation.