First time poster, long time observer.
I am using storyboards for an app I am working on at present, and require more of a transition than just going forward, for going back in particular. Whenever i use this segue i have for going back through a menu, the next button that is clicked on to go to another ViewController, will crash the whole app!
No idea whats going on, i am using this in the implementation file
#import "SlideLeftSegue.h"
#implementation SlideLeftSegue
- (void)perform{
UIView *sv = ((UIViewController *)self.sourceViewController).view;
UIView *dv = ((UIViewController *)self.destinationViewController).view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
dv.center = CGPointMake(sv.center.x - sv.frame.size.width, dv.center.y);
[window insertSubview:dv belowSubview:sv];
[UIView animateWithDuration:0.4
animations:^{
dv.center = CGPointMake(sv.center.x,
dv.center.y);
sv.center = CGPointMake(sv.center.x + sv.frame.size.width,
dv.center.y);
}
completion:^(BOOL finished){
[[self destinationViewController]
dismissViewControllerAnimated:NO completion:nil];
}];
}
#end
This is my header file
#import <UIKit/UIKit.h>
// Move to the previous screen with slide animation.
#interface SlideLeftSegue : UIStoryboardSegue
#end
I am still learning, so if you have any idea whats happening, id appreciate an explanation at a beginner level.
You can achieve that with less code
To present a view controller:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *view = [storyboard instantiateViewControllerWithIdentifier:#"ViewID"];
view.modalTransitionStyle = UIModalTransitionStyleCoverVertical; // you can try the other 3 UIModalTransitionStyle too
[self presentViewController:view animated:YES completion:nil];
To go back:
[self dismissViewControllerAnimated:YES completion:nil];
Related
I've read many question about this issue but I don't figure out what it doesn't work.
Basically I want to change my root controller after the user logged in the or logout from the app. I am also using the storyboard.
My problem is SILoginViewController dealloc's function is never called, in this controller I send Notification and the observer is not removed, so it mess up everything, and after several "login/logout" it receives several notifications.
My AppDelegate :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window setFrame:[[UIScreen mainScreen] bounds]];
BOOL isLoggedIn = [[SIUser aUser] isLoggedIn]; // from your server response
NSString *storyboardId = isLoggedIn ? #"rootViewController" : #"navVcForLogin";
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardId];
return YES;
}
If the user was not logged in and he success the process a Notification is send, here is the handler where I want to change the rootViewController :
- (void)loginSuccessHandler:(id)sender
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
SIRootViewController * vc = [sb instantiateViewControllerWithIdentifier:#"rootViewController"];
[UIApplication sharedApplication].keyWindow.rootViewController = vc;
}
This is the same process for the logout, and here is the notification's handler :
- (void)logoutHandler:(id)sender
{
UIWindow *myWindow = [(SIAppDelegate *)[[UIApplication sharedApplication] delegate] window];
SILoginViewController * vc = [sb instantiateViewControllerWithIdentifier:#"navVcForLogin"];
[UIApplication sharedApplication].keyWindow.rootViewController = vc;
}
The easiest is to show you directly the storyboard :
The implementation in the Storyboard could seems weird but I'm using https://github.com/romaonthego/RESideMenu
I followed their storyboard implementation.
The thing is the SILoginViewController dealloc's method is never called.
But by the way it is working fine, in appearance I mean, when I run the application the behaviour is the good one, but It is sure it will mess out later on.
UPDATE
And I guess it is the common behaviour but there is no transition when the root view controller is changed and there is a black screen for a really short time when the new controller is appearing.
Black screen resolved using : in my AppDelegate.m
- (void)changeRootViewController:(UIViewController*)newRootViewController
{
if (!self.window.rootViewController) {
self.window.rootViewController = newRootViewController;
return;
}
UIView *snapShot = [self.window snapshotViewAfterScreenUpdates:YES];
[newRootViewController.view addSubview:snapShot];
self.window.rootViewController = newRootViewController;
[UIView animateWithDuration:0.3 animations:^{
snapShot.layer.opacity = 0;
snapShot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
} completion:^(BOOL finished) {
[snapShot removeFromSuperview];
}];
}
RootViewController Switch Transition Animation
This probably kind of a duplicate question but I spent hours to figure out this problem.
[currentRootViewController willMoveToParentViewController:nil]; // notify the VC of movements
[self addChildViewController:newRootViewController]; //Add the new VC
[self transitionFromViewController: currentRootViewController toViewController: newRootViewController
duration: 0.15 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
newRootViewController.view.frame = currentRootViewController.view.frame;
}
completion:^(BOOL finished) { //Cleanup from the move
[currentRootViewController removeFromParentViewController];
[newRootViewController didMoveToParentViewController:self];
}];
The code for willMoveToParentViewController and didMoveToParentViewController will notify the ViewController of the changes, and should get your dealloc called, since there is now nothing holding onto the ViewController, unless you have a pointer to it somewhere, then you will need to nullify all your pointers to the code. The solution you tried is only half of what needs to go on to get the transition completed successfully.
I'm playing around with view life cycles & am having trouble changing a view from the load of a different view.
In my ViewController.h i have:
-(void)viewDidAppear:(BOOL)animated{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController2 *viewController = (ViewController2 *)[storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
[self presentViewController:viewController animated:YES completion:nil];
}
However this only causes the view to be between ViewController, and ViewController2 appearing with animation (in a loop).
I used the code in viewDidLoad however neither of the view's loaded (from reading you cannot change view until the viewWillAppear)
Update: When using the code in viewWillAppear, whose view is not in the window hierarchy error is thrown.
How does one change the view from view setup stage?
Update
Using the above code, inside & out of GCD, in viewDidLoad, viewWillAppear & viewDidAppear either results in an infinite loop of animated showing of the ViewController2, or crash on 2nd attempt of segue (result from the loop).
EDITED:
I'm not sure exactly what you're trying to do, but assuming you are wanting the first viewcontroller to appear and then the second viewcontroller to immediately animate on top of the first one, you should be able to accomplish using several options:
First you could just wrap your calls in a dispatch_async call:
dispatch_async(dispatch_get_main_queue(), ^{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController2 *viewController = (ViewController2 *)[storyboard
instantiateViewControllerWithIdentifier:#"ViewController2"];
[self presentViewController:viewController animated:YES completion:nil];
});
Or you could use a show modally segue:
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"myModalSegue" sender:self];
});
}
Or you could use a navigation controller and use a standard show segue (formally push). This one doesn't require the dispatch_async:
- (void)viewDidLoad {
[super viewDidLoad];
[self performSegueWithIdentifier:#"myshowsegue" sender:self];
}
I've posted working examples of all three on: github
It is better to exchange views in loadView method.
- (void)loadView {
CGRect rect = [[UIScreen mainScreen] applicationFrame];
MyView *view = [[MyView alloc] initWithFrame:rect];
[view setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
self.view = view;
}
I m developing a E-commerce mobile application in iOS. I need to know how to move from one UIViewController to another UIViewController with slide animation from top to bottom.
I am using Storyboard.
App needs to works in ios6 and ios7.
Below is the code i used for tranitioning UIViewController
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
MenuViewController *viewController =
(MenuViewController *)
[storyboard instantiateViewControllerWithIdentifier:#"menupage"];
[self.navigationController pushViewController:viewController animated:NO];
Below is the code I tried for a turn page effect and it worked fine. I need the same thing as below for a slide top to bottom
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp
forView:self.navigationController.view cache:NO];
[self.navigationController pushViewController:viewController animated:YES];
[UIView commitAnimations];
The another method
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
MenuViewController *viewController = (MenuViewController *)[storyboard instantiateViewControllerWithIdentifier:#"menupage"];
MenuViewController *viewController1 = (MenuViewController *)[storyboard instantiateViewControllerWithIdentifier:#"menupage"];
[self.view addSubview:viewController.view];
viewController.view.frame=CGRectMake(0,480,320,480);
[UIView animateWithDuration:1
animations:^{
viewController.view.frame=CGRectMake(0,0,320,480);
}
completion:^(BOOL fin){
if (fin)
{
[self.navigationController pushViewController:viewController animated:NO];
[self.navigationController pushViewController:viewController1 animated:NO];
}
}];
Here i get animation in success manner.But i need to load same view controller twice.One is for animation and another one is for normal ViewController Load.If i didnt load second method i get some problem in nextviewController button actions.
Thanks in Advance
Sam.P
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp
forView:self.navigationController.view cache:NO];
instead of using UIViewAnimationTransitionCurlUp use UIViewAnimationCoverVertical
or simply without any view animations, just change a single line.
[self.navigationController presentViewController:viewController animated:YES completion:NULL];
FYI #MaheThiru the push only gives u to and fro transition and for push u need navigation controller. the other transitions like coververtical, pagecurl, crossdissolve and fliphorizontal are provided by modal transition(without navigation controller) which we write as
[self presentViewController:viewController animated:YES completion:NULL];
and i got a small doubt here y r u writing
animated:NO
change it to
animated:YES
maybe it will solve the problem. try it once.
Happy coding
I'm looking for a way to present a modal view over my current UIViewController to basically show a UIActivityIndicator and force users to wait while data is being loaded.
in BaseViewController.m (base class of all my UIViewControllers):
// show loading view
-(void) showLoading
{
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
LoadingViewController *loading = [storyBoard instantiateViewControllerWithIdentifier:#"loadingView"];
loading.view.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:0.7];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:loading animated:NO completion:nil];
}
This works great, but how can I go back to the background view after the loading view should be done?
Need a stopLoading method to go back to the original view:
// stop loading
-(void) stopLoading
{
// code here
}
If I try to present a new view after I present the loading view like so:
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
UIViewController *view = [storyBoard instantiateViewControllerWithIdentifier:#"loadingView"];
[self presentViewController:view animated:YES completion:nil];
The debugger gives Warning:
Attempt to present PropertyPickerViewController: 0x8af6010 on ViewController: 0x8ab23c0 which is already presenting LoadingViewController: 0x8acf530.
Try:
[self dismissViewControllerAnimated:YES completion:nil];
In fact, I'm not sure that it'a great idea to present new controller with animated gif.
The best option is (imo) show UIActivityIndicator + place a view on top on all other views to prevent user from clicking anything.
You must [self dismissViewControllerAnimated:YES completion:nil] first.
Check the Apple Documentation.
I have included the <QuartzCore/QuartzCore.h> framework.
On an IBAction I have this:
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] initWithNibName:#"FilterViewController" bundle:nil];
[UIView transitionFromView:self.view toView:ctrl.view duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
[self.navigationController pushViewController:ctrl animated:NO];
}
When I click the button, the page curls up as you would expect:
When I click the next button (which should curl the page back down) I get this error:
Thread 1: EXC_BAD_ACCESS(code=2, address=0x8)
I think the problem is with the above action (not with the action to uncurl).
What has gone wrong?
EDIT: After a further hour of reading - could it be a memory problem?
I'm not sure but I don't think UIView retains the controller you're passing into it. Assuming you're using ARC, you could try making the FilterViewController into a property.
i.e. In the header add this:
#class FilterViewController;
#interface YourViewController : UIViewController {
FilterViewController *_filterViewController;
}
Then in the implementation change it to:
_filterViewController = [[FilterViewController alloc] initWithNibName:#"FilterViewController" bundle:nil];
[UIView transitionFromView:self.view _filterViewController duration:1 options:UIViewAnimationOptionTransitionCurlUp completion:nil];
[self.navigationController pushViewController:_filterViewController animated:NO];
To make sure it gets retained.
Isn't really mandatory for you to do Page curling effect?
[Try this first]
- (IBAction)searchOptions:(id)sender {
FilterViewController *ctrl = [[FilterViewController alloc] init];
ctrl.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:ctrl animated:YES];
}