I have a storyboard view controller with some labels and a progress bar.
In my view, I load the storyboard view with:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:[NSBundle mainBundle]];
GeodatebaseLoadingViewController *geodatabaseLoading = [storyboard instantiateViewControllerWithIdentifier:#"GeodatabaseLoading"];
[self.view addSubview:geodatabaseLoading.view];
Edit:
I linked the progress bar to the GeodatabaseLoading class, and access it with geodatabaseLoading.progressBar
Am I doing this right?
Thanks
You can't access the progressbar in the viewcontroller instance you have just created because its view won't be loaded until you display it on the screen. This means that there is no progress for you to access at that point.
If you want to update the progressbar in geodatabaseLoading, then you should define an ivar inside GeodatebaseLoadingViewController and set its value whenever you need. Then in GeodatebaseLoadingViewControllers viewWillAppear method, you can set the value of the actual progressbar (which is now guaranteed to exist) using the ivar you had created.
Your code, in its current state would work but it is a poor practice that needs to be changed. You can't randomly add a view to the screen just so you can access an outlet connected to one of its subviews.
Add a new class which inherits UIViewController. Lets call it NorCalKnockOutViewController In interface builder go to the class inspector and set the class of your loading controller to this new class.
Change you code to:
NorCalKnockOutViewController *loading = [storyboard instantiateViewControllerWithIdentifier:#"Loading"];
CTRL drag the progress bar into the header for your class to create an IBOutlet for the progress bar. Call it progressBar.
You can now access it in your code using:
UIProgressBar *pBar=loading.progressBar;
Related
Here is the scenario
Create new project Tabbed Application. Add new controller, TestViewController with XIB file, in the XIB file just add one button with text "TestViewControllerButton".
If I create a button in FirstViewController, and add an action to go to TestViewController, the button in XIB file is displaed.
TestViewController* vc = [[TestViewController alloc] init];
[self presentViewController:vc animated:YES completion:nil];
The problem is when I add TestViewController to tab controller (index 2, start from 0), it does not show the XIB (I mean, the button does not displayed).
Here are my steps. I add UIViewController in Tab Controller, then change the class to TestViewController in Identity Inspector. Then add Tab Bar Item to TestViewController and link it to Tab Bar Controller, so when the last tab is clicked, it linked to TestViewController. But the problem is, the button in the XIB is not displayed (I add the button in TestViewController.xib).
Yeah, off course I can add the button directly in Main.storyboard in my TestViewController, but the idea is I want to manage the UI in TestViewController XIB, and the main.storyboard just load the view in TestViewController image.
Ok, I add some screenshot to make understand. This screen runs well when I do programmatically, run in UIViewController (code above - self presentViewController:vc animated:YES completion:nil).
When I run from Tab
The setting I think is already correct (since it runs well in UIViewController)
Already set file owner to the TestViewController
Already bind the outlet
Thanks!
I think you are using the ViewController of size Inferred , Change it to iPhone 4 inch in Attribute Inspector (Simulated Metrics -> Size and set the button frame acc. to that .
Hope this help :)
Of course it will not show the controls. See, you are using two different view controllers at these places. In the xib, you have actually added your button and hence when an instance of your testViewController is created from the xib, it has the button and its associated action with it. However, in the case when you add a viewController in your storyboard and set its class to be that of TestViewController, all you are doing is setting the class type of the new view controller to be TestViewController. But you are not providing any information by which the storyboard can know that it has to create the new instance of testViewController from the image saved in its XIB. So it just crates a new view controller of type TestViewController, using its image from inside the storyboard (without the button in it).
So to get your view controller from the xib you will have to override initWithCoder: method inside your TestViewController implementation and return an instance of your viewController from the XIB. Something like:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
return [self initWithNibName:nil bundle:nil];
}
In my app, I need to go to another UIViewController with a button click, but when I did it in the new UIViewController it displays only what I set programmatically.
I used:
NewSubject *NewS = [[NewSubject alloc] initWithNibName:nil bundle:nil];
[self presentViewController:NewS animated:YES completion:nil];
"NewSubject" is the UIViewController I need to go too, however I want the computer to display also the stuff I set by the Storyboard.
Have you set in the Storyboard, in the NewSubject View Controller, in the third tab (Show Identity Inspector) the StoryBoard ID?
You should set it to some name, such as "NewSubject" and use it as follow:
NewSubject *NewS = [self.storyboard instantiateViewControllerWithIdentifier:#"NewSubject"];
[self.navigationController pushViewController:NewS animated:YES];
I want the computer to display also the stuff I set by the Storyboard.
If you're using a storyboard, -initWithNibName:bundle: is the wrong method to use. You can use UIStoryboard's -instantiateViewControllerWithIdentifier: method to create a new view controller that's defined in a storyboard, but the more typical approach is to have your button trigger a segue between the two view controllers.
Try this:
While editing your storyboard, control-drag from your button to the new view controller. A popup menu should appear that lets you choose how you want to transition between the view controllers -- push (push the new controller onto the top of the navigation stack), modal (present the view controller modally), etc. Pick the appropriate one.
In simple cases, you're done -- there's no need to write any code just to get the transition to happen. The segue takes care of creating the new view controller and performing the transition for you. However, you often want to pass some data from the existing view controller to the new one. If that's the case, implement -prepareForSegue:sender: in the existing view controller -- this method gives you a chance to pass whatever data you need. It'll look something like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// It doesn't hurt to check that it's the segue that you expect
if ([segue.identifier isEqualToString:#"MySegueIdentifier"]) {
NewViewController *newVC = segue.destinationViewController;
// This is your chance to set properties or call methods to pass data to the new view controller
newVC.foo = self.foo;
newVC.bar = self.bar;
}
}
I got a view controller named IntroViewController in my storyboard and I want to add this as a child to another view controller like this:
IntroViewController *introViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"View1"];
[introViewController.textLabel setText:#"test"];
[self addChildViewController:introViewController];
On the IntroViewController I've put a label named textLabel on it in the storyboard, if I run the program it works and shows me the view controller, but the text doesn't get changed. Any idea how I can fix this?
When you instantiate a view controller from a storyboard, the view is not loaded until it is actually presented on screen. At the point in your code you have posted introViewController.textLabel is nil.
One option you could do is add a property to your IntroViewController class and instead set that:
introViewController.initialText = #"test";
Then, inside -viewDidLoad of your IntroViewController the label will be instantiated so you can make the call:
[self.textLabel setText:self.initialText];
It is also worth noting that most of the time it would be recommended to have a view controller be the one to set values on the views it owns, rather than some other view controller.
in my iPad-app I am trying to present one of my views with a modal formsheet-style.
Here's some code:
-(void)present
{
SecondViewController *modal = [[SecondViewController alloc]init];
modal.modalPresentationStyle = UIModalPresentationStyleFormSheet;
[self presentModalViewController:modal animated:YES];
}
I am using Storyboard, and I have put stuff like a textView and toolbars in the view I'd like to show. I have set the right class in Identity Inspector, and in the class-files I have checked that it's the right view appearing with putting NSLog(#"Right view");
When calling the void present, a view is appearing, but only as a dark-white square. Nothing og my content from Storyboard is in it, I even tried changing the background color of the view and the textView to see if something was just outside the square, but the whole thing stayed white. It feels like it's not using the view I created in storyboard, but I have set it to the correct class, and the NSLog gets printed out when calling it. I have not connected the two views in any way in Storyboard, the SecondViewController is just floating around, so that might be the problem? The button that calls for -(void)present is created programmatically, so I can't ctrl+drag it to the button either.
Why is it showing an empty version of my class?
In the "Identity Inspector" set a "Storyboard ID" for your ViewController, and then present it like this:
-(void)present
{
SecondViewController *modal = [self.storyboard instantiateViewControllerWithIdentifier:#"myStoryboardID"];
modal.modalPresentationStyle = UIModalPresentationStyleFormSheet;
[self presentModalViewController:modal animated:YES];
}
And if you're using iOS6, presentModalViewController:animated: is deprecated, so use this:
-(void)present
{
SecondViewController *modal = [self.storyboard instantiateViewControllerWithIdentifier:#"myStoryboardID"];
modal.modalPresentationStyle = UIModalPresentationStyleFormSheet;
[self presentViewController:modal animated:YES completion:nil];
}
Your problem is that you're assuming the program will intrinsically know where to find the, already laid out, view for this controller when that's simply not how storyboards work. The code you list about will create a view controller, but without an associated view it will simply show as a black square.
There's a few ways to solve your dilemma:
Add the modal transition as a segue in the view controller, this would be the simplest way and is what iOS storyboards expect you to do.
Move the view from the storyboard to an external .xib and call the initWithNibName:bundle: method to load this as your view controller's view. This is the best solution if you just want to programmatically load the view.
Load the view from your storyboard programmatically with the instantiateViewControllerWithIdentifier: method, this is probably a bad idea as it goes against the design of storyboards.
I can elaborate on those if you want.
I have a problem with switching views. I'm using a simulator with xcode 4.2
Storyboard contains:
NavigationController (initial view controller)
UIViewController which has relationship with the navigation controller
UIViewController (paired with my custom class: ViewEntryImageController) which hasn't got any relationship. Contains a button, a bottom toolbar with some toolbar button.
User come into the UIViewController, where he can see a ScrollView and in ScrollView some images.
Images has a gesture:
UITapGestureRecognizer *recognizer=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(openEntryImage)];
[image addGestureRecognizer:recognizer];
[recognizer release];
The openEntryImage function:
(IBAction)openEntryImage
{
ViewEntryImageController *controller=[[ViewEntryImageController alloc]initWithNibName:nil bundle:nil];
controller.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:controller animated:YES];
[controller release];
}
When I try to tap the image, the openEntryImage works as well (the effect is correct), but I don't see my ViewEntryImageController view and my buttons, I'm only see a black window.
I try to put a NSLog line into the ViewEntryImageController viewDidLoad function, and it works, so what is the black window and where is my view controller?
When I try to use pushViewController, on the new view I found a navigation toolbar with a back button, but no other controls.
I tried another version, I created a UIViewController class, but now with a xib file. I used it instead of ViewEntryImageController and it works. Why?
I want to use this controller in storyboard too.
The ViewEntryImageController class by itself has no information about how to build the dialog. But you can instantiate your view controller on your own from the storyboard:
UIStoryboard *myStoryboard = [UIStoryboard storyboardWithName:#"StoryboardFileName" bundle:nil];
ViewEntryImageController *controller = (ViewEntryImageController *)[myStoryboard instantiateViewControllerWithIdentifier:#"ViewEntryImage"];
This assumes a storyboard name of StoryboardFileName and that the view entry image controller has an identifier of ViewEntryImage set in the view properties (Attributes inspector, section "View Controller").
Try it like this :
ViewEntryImageController *controller=[[ViewEntryImageController alloc]initWithNibName:#"ViewEntryImageController" bundle:nil];
If you don't use .nib names but rather use storyboards, it's a bit harder. Create a segue from the controller to the ViewEntryImageController controller by holding ctrl and dragging from one view to the other. Click this segue and give it an identifier.
Then use the [self performSegue:#"identifier"]; function to present the next view.