Reloading UIModalViewControllers - objective-c

I have a super simple presentation for iPad with few modal views. At every View user makes a simple action (like dragging a slider), after that appears UIButton "Next" what presents new modal View above previous. Button in last view connects with first view by a modal segue. So app needs to work in recursive way. But after first time presentation goes (from the second loop starts), all Views presented with all actions done in them. So I want that all app ModalViewControllers reloads to the default state every time user taps button on the last View.
Can I implement this behaviour only set it in -prepareForSegue of UIButton in last ModalViewController or it's a more global issue? If so, how to implement that?

Implement viewWillAppear in every ViewController will give you an opportunity to reset the view before the view gets to the screen. When you come back to a ViewController from another viewController, viewWillAppear gets called.
-(void)viewWillAppear:(BOOL)animated
{
NSLog(#"viewWillAppear");
[super viewWillAppear:animated];
//Reset your view (i.e. hide next button etc.)
}

Related

Create back button

How do I create a custom back button on one of my storyboards, when I do a segue and I say push it creates a back button on Mac with but when I do a modal or model it does not create a back button?
Modally presented view controllers do not automatically get close buttons.
self.navigationController.leftBarButtonItem = ...
A pushed view controller will automatically create a back button if the navigation controller is shown.
You will have to create your own back button. In the view controller that you have presented via the modal transition, you have to put a toolbar on it. Put it at the top and if using autolayout set the constraints top, both sides and height. Then place a barbuttonitem in the toolbar. You can select a system button like done or cancel. Make sure the new view controller is the class that you created. Now you can control drag from the barbuttonitem to your .h file and connect an IBAction. Call it dismiss or something like that. In that method call [self dismiss viewcontroller:animated completion:nil]. This will bring you back to the original view controller. I am not a my computer right now so I am not sure the exact wording of the dismiss method, but it will auto fill for you. Good luck.
As Douglas explained, you need to create property of the button (UIButton or BarButtonItem) and in the viewcontroller .m file connect
- (IBAction)backButton:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
with the button. This will dismiss the current view controller and bring you back to the previous one :)

Dismiss modal segue

I am trying to understand modal vs push segue and read few Q & A like this and this. One point I am confused from these answers is "The presenter should take care of dismissing the VC it presented."
For example, the example I am writing shows UIPageViewController something like the example available here, with a button at bottom of the page with name "Skip".
In story board I have created a segue (of type Modal) from "Skip" button to another "View Controller" (let us say LoginViewController), but where do I need to dismiss the UIPageViewContoller (if at all required) and how?
EDIT:
After little bit more reading, it seems UIPageViewController (Which has Skip button) should take care of dismissing LoginViewController (because UIPageViewController is the presenter).
In my case, after Login complete, I would like to navigate to "Menu" page, then how can I ask UIPageViewController to dismiss the "LoginViewController" and move to MenuController? I couldn't find any example on how this works.Any help would be appreciated!
As per the tutorial link you have given in question.
There is a APPViewController which is root for the UIPageViewController and also in AppDelegate, so on top of that view, require a Skip button which is above all the subViews in AppViewController. So its IBAction event will be in AppViewController only.
Now first change your AppDelegate self.window.rootViewController to LoginViewController.
In LoginViewController viewDidLoad event, presentModal UIPageViewController.
Now in its action event of skip button, you can write like this:
[self dismissViewControllerAnimated:YES completion:nil];
So it will automatically dismiss all your AppChildViewControllers, and will display LoginViewController, which is already behind.
This is just a base logic to achieve your goal, you might require to change code as per your project implementation.
Hope this helps.
First dismiss the UIPageViewController and then using delegate or block methods (whatever suitable) to get notified when you press the skip button in the parent controller and then calling LoginViewController.

How to modify objects within a modal view?

I have an app with several views. Taking into consideration the large main view, called MyView1, it is controlled by MyView1Controller. Within MyView1, there is a button that causes a modal segue to another view, whose controller is also MyView1Controller. This modal view has a couple UILabels, and a button that terminate the modal view, bringing the user back to MainView1.
Here is the problem... Let's say in my modal view there is a UILabel called sampleLabel. While in MyView1, a button is pressed, which executes the code:
sampleLabel.text = #"changed";
Since the UILabel named sampleLabel is not on screen for MyView1, and instead is part of the modal view from MyView1, nothing happens. However, when I click on the button to view the modal view from MyView1, the UILabel hasn't changed.
This is even more puzzling since the main MyView1 and the modal view that segues off of MyView1 are controlled by the same view controller, MyView1Controller.
Can someone please tell me how I can make code that executes during the user's interaction with MyView1 change things in the modal view, so that when they press the button and segue to the modal view, the UILabel's have already been changed?
Thanks!
First of all, Apple recommends (and it makes life a lot easier) to have one view controller for each view. So you should have a second view controller. In the second view controller you would have a property called sampleLabel. In the first view controller you could use different methods to set the sampleLabel.text. I would probably create a separate sampleLabelText property in the first view controller (could be an NSString *) and set it to the text you want when the user presses a button. Then in your
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
you would get your second view controller and set its property like this:
SecondViewController *svc = [segue destinationViewController];
svc.sampleLabel.text = self.sampleLabelText;
That's it. Hope this helps.
So I have had a similar issue that I resolved through 'delegation' but not through a segue schema. Here is a link to the stackoverflow question and my answer. Delegation
Hopefully this gets you going in the right path. Instead of modally presenting a view, I push a new viewcontroller onto a navigation stack but the same answer should apply, hopefully :P

How would I create a loading screen with a start button that leads to the rest of my app?

In my app, I would like a loading screen which has a start button, and when the user presses the start button, it displays my the actual parts of my application.
I can't use a Default.png because i need the functionality of the start button. And since my rootViewController is a tabBar, I can't simply add my screen as a subview, because then my loading screen just appears in each individual tab.
Any ideas?
You could create a new view controller and set that view controller as the root view controller. In the new view controller, create a UIImageView with the loading image and a UIButton where you want it. Then you could go in the storyboards and make the button transition to the "actual parts of [your] application".
Hope this helps!
There are several ways to do it. Assuming your app spends very little time in the Start Screen, I would implement it as a modal view controller that I display over the root tab view.
After you load your root tab bar view for the first time, present the Start Screen view controller without animations.
[tabBarViewController presentViewController:startViewController animated:NO completion:NULL];
If you do this early enough (e.g., in your app delegate's didFinishLaunching: method), the start screen will be the first thing the user sees. It's hard to say exactly where you should insert this code since you haven't said whether you are using storyboards or a default nib or loading a view manually etc.
When the button is pressed, simply dismiss the startViewController.

UIViewControllers problems

Hi there and thank you in advice for your help. I have a really strange problem while working with ViewControllers in Xcode4. First of all I have to say that I'm not using storyboards and I prefer to create any UI element programmatically. So I've set a UIButton and I want that, when pressed, it brings me to a new view controller. This is the code I'm using for a button:
-(void)settingsAndExportHandle:(UIButton *)buttonSender {
SettingsViewController* settingView = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
settingView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:settingView animated:YES];
}
This buttons is initialized and allocated in the viewDidLoad method of the RootViewController. I want to switch to the other view controller (in this case SettingsViewController) when I press the button.
The strange thing is that when I press the button, the animation that flips the controllers goes well, but when it finishes I obtain the EXACT same things that I had on the RootViewControllers (same custom views, same buttons, same all!). The question is: what I'm missing?? I have to say that I use ARC (automatic reference counting) so I can't release or dealloc the views and buttons I've created on my RootViewController.
Any help will be appreciated. Thank you all!
Pushing and and modally presenting view controllers does not deallocate the view controller that presented them. It simply adds the additional view controller to the stack. You'll need to implement a callback method so that when the user hits the button to flip back to root view controller, your settings view controller lets the root view controller know what's about to happen so you can call a method you've written to reset the interface back to whatever state you need it at. You may also be able to use viewWillAppear: but that's a little messy.
However, according to the Apple Human Interface Guidelines, the user expects that when they push a view controller or modally present it, the view controller they were on will save state and be exactly the way they left it when they came back. It's disconcerting and annoying when state is not preserved while in a navigation controller context. It is especially annoying when it's modally presented.
Think about this - A user is in a hypothetical Mail app. They start typing out an email and set a font size and a color. They tap on the add attachment button, which brings up a modal view controller that allows them to select a picture. They select the picture and the modal view is dismissed, and in your implementation, the mail composing interface would have reset and the email content would be gone or at the very least the selected font size and color would be back to the default. That's not a good experience.