I have two scenes. A regular, full-screen iPad view and another popover view. Tapping a button loads the popover view with no problems. In the popover view I have a button that will perform some action and is also linked to a storyboard modal transition.
The idea is that pressing the button from the popover view will save the user's selection state and send that data to the main view. I have no issues with the data saving, that works just fine.
The issue I am having is that when I press the button from the popover view, the main view's viewDidLoad method actually completes before the popover view's IBAction method does. So the main view gets the data, but since the view already loaded it is not able to update the label in time.
I tried creating multiple popover view scenes and added multiple buttons to the main view that will link to these new scenes. The weird part is that some of them work just fine. Some of them will perform the IBAction method and then it transitions back to the main view via a modal transition. There seems to be no rhyme or reason why one loads before the other.
I suppose a possible solution would be to perform the transition manually within the IBAction method of the popover view. I am definitely new to this so there may be something fundamental about transitions that I am missing.
In the view controller of view on which the button is present... When segue is going to be performed. You can pass data in
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
This method is called before the view is loaded..
If you are calling a popover so the main screen should not call viewDidLoad method because the main view still on the back. It should be calling the viewWillAppear and the viewDidApper methods instead.
Can you check this? I think you should refresh the main screen after one of these two methods are called.
Give it a try and tell me the results.
Related
I have a segue that navigates from FirstViewController to SecondViewController. This happens by the press of a button. The code for the button is
- (IBAction)segue:(id)sender {
[self performSegueWithIdentifier:#"myIdentifier" sender:self];
}
This happens correctly when i press the button.
What i am trying to do is fire this method from another view. I tried doing
FirstViewController fvc = [[FirstViewController alloc] init];
[fvc segue:nil];
When i try this, I get the error message, Reciever has no segue with identifier 'myIdentifier'
How do i fire this segue programatically from another view?
There are a few issues here, but they boil down to a couple of key points:
Segues are a storyboard thing, so view controllers only "know" about segues if they're instantiated from a storyboard.
A view controller must be onscreen to perform a segue.
Segues are transitions from one specific view controller to another specific view controller.
So, in your snippet:
FirstViewController fvc = [[FirstViewController alloc] init];
[fvc segue:nil];
The first problem is that alloc-init-ing gives you an instance of FirstViewController that doesn't know anything about the storyboard it came from, so it doesn't know anything about segues. (This alone could be fixed using [instantiateViewControllerWithIdentifier:][1], but that doesn't solve your whole problem.) A second problem is that this instance doesn't fit anywhere into the UI hierarchy -- it hasn't been presented as a modal view controller, it's not the top view controller in the current navigation controller, it's not the visible window's root view controller, etc. In order to transition the screen from one view to another, the first view needs to be onscreen.
What it sounds like you want to do is transition from what's currently onscreen to the target of this segue. But the notion of a storyboard segue isn't just a transition with a destination -- it's a source, a destination, and a transition or relationship between them. If you have a different source view, you need a different segue. So, if you already have a segue from FirstViewController to SecondViewController, and you want to make a similar transition from OtherViewController (assuming that's the one onscreen now) to SecondViewController, you need to make a second segue connecting OtherViewController to SecondViewController.
I'm working on an app that I need to change the text of text view of child view controller from a method in the parent view controller.
I have a button in child VC, when it's pressed, the view doesn't change, but a method in parent VC is called, and another method in parent VC will change the text of text view in child VC.
[self.delegate buttonPressed];//in child VC, call method in parent VC
It was working before I use storyboard.
In the parent vc, I just had code below,
childViewControler.textViewName.text=#"something";
Now I changed to storyboard, by using NSLog, I know the method to change the text is called. But no text is displayed.
I'm thinking I might add something since I am using storyboard now?
Can someone give me advice?
Thank you.
The childViewControler variable in your parent view controller needs to point to the instance of your child view controller class created by the segue. If you don't assign anything to it, it's nil, and any messages to it do nothing.
It's unclear from the code you've posted whether it's a property, instance variable, or local variable; here's how you could do it with an instance variable:
#implementation ParentViewController
{
ChildViewController *childViewController;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// if you have multiple segues, check segue.identifier
// so you only do this for the correct segue
childViewController = segue.destinationViewController;
}
- (void)buttonPressed
{
childViewController.textViewName.text=#"something";
}
#end
The key bit is in prepareForSegue:sender: -- you need to make sure that the childViewController variable points to the view controller created by the segue.
It's also possible that your problem results from still having some old pre-storyboard code that allocs and inits a child view controller and puts it into your childViewController variable. In that case, you'd have two instances of that view controller class around: the one created by the segue and the one you made. Only the one created by the segue is hooked into the UI, so any changes you make to the other won't be visible. You can solve this problem by getting rid of any code that creates and presents the child view controller -- the storyboard takes care of all that now, and prepareForSegue:sender: is the only place you need to get a reference to the child view controller.
I am creating an app using iOS 5 SDK. I managed to push views using the Storyboard's Segues, but I cannot find the proper way to pop the current view and go back to the previous one.
I am not using any navigationController (the app doesn't have any top or bottom bars).
I don't think using modal or push segue the other way would be the solution as it instantiates a new controller.
Do I have to use a custom Segue with the opposite animation and deletion of the view at the end ? Or is there a better way ?
Storyboards in iOS 5 don't provide a "no-code" way to return from a segue -- that's something you'll need to implement yourself.
If you use "push" segues (which require a navigation controller), use the navigation controller's popViewControllerAnimated: method to undo the last push segue. (Or other methods to undo more; see the UINavigationController documentation.)
If you use "modal" segues, call dismissViewControllerAnimated:completion: on the view controller which presented the current view controller (which you can get from its presentingViewController property).
Update: In iOS 6 and later there's unwind segues for going "back" in a storyboard. It's still not a no-code solution -- and it shouldn't be, because you need to be able to do things like differentiating between "Done" and "Cancel" exits from a modal view controller. But it does let you put more of the semantic flow of your app into the storyboard. Apple has a tech note that describes them in detail, and they're also covered in the video from WWDC 2012 Session 407.
You could try calling [self dismissViewControllerAnimated:YES completion:nil]; from the controller you want to dismiss (whether the controller has been pushed, or shown modally).
Here is the related documentation : UIViewController Class Reference
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.
Just to clarify.
In the class that was pushed. Simply wire up the following and the controller and view will be popped off.
[self.navigationController popViewControllerAnimated:YES];
Create Segue type "Custom" on your stroyboard. This can be from a button.
Create a new UIStoryboardSegue class named "popSegue"
In the popSegue.m file add the following;
-(void)perform{
UIViewController *sourceViewContreoller = [self sourceViewController];
[sourceViewContreoller.navigationController popViewControllerAnimated:YES];
}
-In the storyboard editor.
-Select the segue and change the Segue Class to "popSegue"
-Set the Identifier to "popSegue"
Done!
You can use the same "popSegue" class throughout your project.
Hope this helps
I'm using Xcode 5 also and here's how it's done. First, in the view code file that pushed the other, create an IBAction method in the .h file such as this:
- (IBAction)exitToHere:(UIStoryboardPopoverSegue *)segue sender:(id)sender;
Then in the .m file add this:
- (IBAction)exitToHere:(UIStoryboardPopoverSegue *)segue sender:(id)sender {
}
You can add any cleanup code you want executed in this method. Next go to your storyboard and select the pushed view. I assume you've got some kind of button on the view that the user taps to signal he's finished. Click on that button, hold down the key and drag to the the green box below the view which is the Exit. Release the mouse button but continue to hold the key. A popup will appear and your method will show in the list. Select that method. Now when the user clicks on the button, the view will pop and you'll be returned to the starting method.
Using StoryBoard, I've created my first view controller with a button. It segues and opens up a second scene. The second scene has a button. You tap the button, it pulls up data. I don't want to have to tap the button on the second scene to get the data to load. I would have put it in a viewdidload but it doesn't seem to work. (Yes, I'm a newb.) I've created an Objective-C Class called ResultsView and connected it to the scene. I'm just wanting the second scene to execute a couple of lines of code when it is segued to. Can you tell me how to get this done?
You can setup for the segue in the prepareforSegue method.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Do your stuff to setup the Segue
}
And also the view lifecycle APIs will get called.
Hello i have a very simple question, I have initialized some variables and started the motion manager updates on the "viewDidLoad" method, but after i finish using it I am closing the window and returning to the previews one. My question is whether the method is being called everytime i open that window trough a segue in the storyboard. (Since the description says it does it when it loads it to memory not to the screen)
I am closing the window by telling that window that the previous one is its delegate like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Drawing"])
{
DrawingViewController *temp = segue.destinationViewController;
temp.delegate = self;
}
}
and then when the user clicks the closing button in the new window it tells the delegate (the previous screen) to close him:
- (IBAction)cancel:(id)sender
{
[self.delegate DrawingViewControllerDidCancel:self];
}
This is the closing method:
- (void)DrawingViewControllerDidCancel: (DrawingViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Oh and if someone would be so kind to tell me why is it that by calling self i am closing the other window, (Because i think self refers to the delegate not to the one that i want to close).
Thank you very much!
Put some log statements in the viewDidLoad method, this will be easy enough to find out for yourself. You can't expect a view controller that has been dismissed to be hanging around in memory - it could get unloaded at any time due to a low memory situation. You've even called it temp ;)
dismissModalViewController is passed along the view controller chain, you can call it on the modal controller itself or the presenting controller, it has the same effect. The currently presented modal view controller is dismissed.
From the documentation:
If you present several modal view controllers in succession, and thus build a stack of modal view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.