How to change speed of segue between ViewControllers - objective-c

Is it possible to control segue speed?
I have checked the documentation but there is no given method by Apple.
But I am more looking for ideas to hack in and change lower level code to make segueing in slow motion.

Below code is of custom segue, and you can set duration of transition in code.
- (void)perform
{
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
[UIView transitionFromView:src.view
toView:dst.view
duration:3.0
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:NULL];
}
Sample project is here in GitHub:https://github.com/weed/p120805_CustomSegue
You can download and just run it. I wish this is help for you.

to prevent zombies creation i think better to do use subview add/remove as well:
- (void)perform
{
UIView *src = ((UIViewController *) self.sourceViewController).view;
UIView *dst = ((UIViewController *) self.destinationViewController).view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
[window insertSubview:dst aboveSubview:src];
[UIView transitionFromView:src
toView:dst
duration:1.5
options:UIViewAnimationOptionTransitionCrossDissolve
completion:^(BOOL finished){
[src removeFromSuperview];
window.rootViewController = self.destinationViewController;
}];
}
this is if you are not using navigation controller!

Related

Why do my touch event not work?

I have declared a void touchesbegan method in my controller but it doesn't work! i don't know why. i have an image view which i plan to click it to move to next controller. so i set the touches began method. i have linked the image view in the xib file but when i click the image. nothing happens. Please help, Thanks.
ViewController.h
#import <UIKit/UIKit.h>
#interface imageViewViewController : UIViewController
{
IBOutlet UIImageView *testing;
}
#property(nonatomic, retain) IBOutlet UIImageView *testing;
#end
ViewController.m
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if(touch.view == testing)
{
TestViewController *testviewcontroller = [[TestViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:testviewcontroller animated:YES];
}
}
#end
P.S.
here i tried another method using tap gestures.
testing is the name of my image view. as u can see i comment out the ns log in the imagedidtapped method. it works til that point. however when i tried to navigate it out to another page it fails.
- (void)viewDidLoad
{
UITapGestureRecognizer *tapRecognizer;
[testing setTag:0];
[testing setUserInteractionEnabled:TRUE];
tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewDidTapped:)] autorelease];
tapRecognizer.numberOfTapsRequired = 1;
[testing addGestureRecognizer:tapRecognizer];
[self.view addSubview:testing];
[testing release];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)imageViewDidTapped:(UIGestureRecognizer *)aGesture {
UITapGestureRecognizer *tapGesture = (UITapGestureRecognizer *)aGesture;
UIImageView *tappedImageView = (UIImageView *)[tapGesture view];
switch (tappedImageView.tag) {
case 0:
//NSLog(#"UIImageView 1 was tapped");
[self navigate];
break;
case 1:
NSLog(#"UIImageView 2 was tapped");
break;
default:
break;
}
}
-(void)navigate
{
TestViewController *testviewcontroller = [[TestViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:testviewcontroller animated:YES];
}
The problem is that by default userInteractionEnabled is NO for a UIImageView so you won't get any touches. Set it to YES.
Also the message handling for touchesBegan is really complicated. You'll be much happier if you attach a UITapGestureRecognizer to the image view.
EDIT: Now you say your touches handling is working, but the navigation is not taking place. So let's concentrate on this part of your code:
-(void)navigate
{
TestViewController *testviewcontroller = [[TestViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:testviewcontroller animated:YES];
}
Put logging in there to make sure navigate is being called! If it isn't being called, you need to figure out why your other code is not running and calling it. If it is being called, then the problem is probably that self.navigationController is nil, i.e. you are not inside a navigation interface to start with.

UIButton not working in second time (objective-C)

I have a button in my first screen for loading a small game here is the code:
- (IBAction)playButtonPressed:(id)sender
{
[self startGameWithConfig:[RootViewController singleplayerGameConfig]];
NSLog(#"play again");
}
and inside of my game page I have a button to back to the first screen when I used this button I can back but my playButtonPressed not working any more, it print the NSLog but
the button it's not loading the game any more
here is my return button:
- (IBAction)return:(id)sender {
RootViewController *b = [[RootViewController alloc] init];
[self presentModalViewController:b animated:YES];
}
would you please help me to this implementation
Thanks in advance!
and here is my startGamingWithConfig
- (void) startGameWithConfig:(GameConfig *)config
{
// fade in the loading screen to hide load time
[_loadingView setHidden:NO];
[_loadingView setAlpha:0.0f];
[UIView animateWithDuration:0.2f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^{
[_loadingView setAlpha:0.0f];
}
completion:^(BOOL finished){
CardsViewCtrl* newController = [[CardsViewCtrl alloc] init];
newController.gameConfig = config;
AppDelegate *delegate = (AppDelegate *)[[UIApplication
sharedApplication] delegate];
[delegate.navController pushFadeInViewController:newController
animated:YES];
}];
}
It is a bit hard for me to understand where this code is since there are no headings but it looks like when you are attempting to go back to the RootViewController you are creating a new one and pushing that on the stack. You want to make sure that your topViewController is removed, not adding more views.
So for a starter try to replace return method:
- (IBAction)return:(id)sender {
RootViewController *b = [[RootViewController alloc] init];
[self presentModalViewController:b animated:YES];
}
with this:
- (IBAction)goBack:(id)sender {
[self dismissModalViewController];
}
I am not sure how you have your view hierarchy setup, but if you have a working navigationController than try using [self.navigationController popNavigationController:YES];

Transition from one UIViewController to another in a custom segue

This custom segue visually works correctly but there is an warning when completed.
Warning: Attempt to present <DestViewController: 0x21059f40> on <SrcViewController: 0x1fd50cf0> whose view is not in the window hierarchy!
Any help on how to get this to work without the warning would be much appreciated, have spent more time on this than i should. Not even sure if I should care about it since it is a warning.
- (void)perform {
UIViewController *src = (UIViewController *)self.sourceViewController;
UIViewController *dst = (UIViewController *)self.destinationViewController;
dst.view.alpha = 0;
[UIView animateWithDuration:0.5
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[src.view addSubview:dst.view];
dst.view.alpha = 1;
}
completion:^(BOOL finished){
[dst.view removeFromSuperview];
//need to understand why this throws a warning but still works
[src presentViewController:dst animated:NO completion:^(){
[src reset];
}];
}];
}
UPDATE
There was a call to stop a MPMoviePlayerController in the reset method on the src UIViewController. For some reason that was causing the issue, once removed this segue works perfectly. See my answer below for final implementation of segue.
You are removing the view from superview i.e src.view and presenting the same viewController after it , so it is showing warning.
Try this (If this doesn't work tell me):
[UIView animateWithDuration:0.5
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
dst.view.alpha = 1;
}
completion:^(BOOL finished){
[src presentViewController:dst animated:NO completion:^(){
[src reset];
}];
}];
}
although the original issue was caused by something outside of the segue, as mentioned above, i thought i would post the full working segue code for others who may end up here. The delegate in this example is a custom UIViewController container where the child UIViewContainers where added as children in the following way:
[self addChildViewController:childController_];
[self.view addSubview:childController_.view];
segue.h
#import <UIKit/UIKit.h>
#interface COFSimpleSegue : UIStoryboardSegue
#property (assign) UIViewController *delegate;
#end
segue.m
#import "COFSimpleSegue.h"
#import <QuartzCore/QuartzCore.h>
#implementation COFSimpleSegue
#synthesize delegate = delegate_;
- (void)perform {
UIViewController *src = (UIViewController *)self.sourceViewController;
UIViewController *dst = (UIViewController *)self.destinationViewController;
dst.view.frame = delegate_.view.bounds;
dst.view.autoresizingMask = delegate_.view.autoresizingMask;
[src willMoveToParentViewController:nil];
[delegate_
transitionFromViewController:src
toViewController:dst
duration:0.5f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^(void){}
completion:^(BOOL finished) {
[dst didMoveToParentViewController:delegate_];
[src removeFromParentViewController];
}
];
}
#end

How Popup Keyboard After Segue to New Naviagtion Controller Animation Has Finished

I segue from a tableview to detail view controller using custom segues.
#implementation QuickNoteFlipSegue
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
UIViewController *dst = (UIViewController *) self.destinationViewController;
dst.navigationItem.hidesBackButton = YES;
[UIView transitionWithView:src.navigationController.view duration:1.00
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
[src.navigationController pushViewController:dst animated:NO];
}
completion:^(BOOL finished){
if (finished) {
}
}];
}
#end
What I would like to do it when the transition has finished, popup the keyboard for my textview.
I currently do this by calling
[textView becomeFirstResponder];
This pops up the keyboard OK but before the transition animation has finished. How to detect when the animation has finished before I popup the keyboard?
I should maybe put something is the completion of the animation, but how to make the custom segue aware of the textview in it's destination?
Do:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[textView becomeFirstResponder];
}
Add a method to your DestinationViewController:
-(void)openKeyboard
{
[textView becomeFirstResponder];
}
Then change your perform method:
- (void) perform {
UIViewController *src = (UIViewController *) self.sourceViewController;
DestinationViewController *dst = (DestinationViewController *) self.destinationViewController;
dst.navigationItem.hidesBackButton = YES;
[UIView transitionWithView:src.navigationController.view duration:1.00
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
[src.navigationController pushViewController:dst animated:NO];
}
completion:^(BOOL finished){
if (finished) {
[dst openKeyboard];
}
}];
}

Forcing UIAlertView into landscape mode

I need to display a UIAlertView in landscape mode. I tried the obvious, setting the transform in the willPresentAlertView: delegate method to no avail:
-(void) willPresentAlertView:(UIAlertView *)alertView {
alertView.transform = CGAffineTransformMakeRotation(M_PI_2);
}
Any suggestions on how to fix this?
Have you tried in the didPresentAlertView?
- (void)didPresentAlertView:(UIAlertView *)alertView
{
// UIAlertView in landscape mode
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationDuration:0.1];
alertView.transform = CGAffineTransformRotate(alertView.transform, 3.14159/2);
[UIView commitAnimations];
}
It should rotate automatically if you're using UIViewController.
Did you forget to return YES for the desired orientations in shouldAutorotateToInterfaceOrientation?
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES; /* auto rotate always */
}
What is the orientation of the view that shows the alert? I had the same problem, I tried to show an UIAlertView inside a landscape view but always appeared in portrait orientation. So, I forced the orientation of the status bar:
[[UIApplication sharedApplication] setStatusBarOrientation:theOrientation];
That worked to me.
Before the Alert Window appeared , Set the current window display at the top. If not do this ,you can see the alert window's rotate animate.
-(void) willPresentAlertView:(UIAlertView *)alertView {
[UIView setAnimationsEnabled:NO];
self.view.window.windowLevel = 2003;
}
Rotate the Alert Window
-(void)didPresentAlertView:(UIAlertView *)alertView
{
UIWindow * alertWindow = alertView.window;
alertWindow.transform = CGAffineTransformMakeRotation(M_PI / 2);
alertWindow.bounds = CGRectMake(0, 0, SCREEN_HEIGHT,SCREEN_WIDTH);
alertWindow.center = CGPointMake(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(showLandscapeAlertView) userInfo:nil repeats:NO];
}
After the Alert window rotated, move the current window back.
-(void)showLandscapeAlertView {
self.view.window.windowLevel = 0;
[UIView setAnimationsEnabled:YES];
}
I was struggling with quite the same issue lately. For me solution was using UIAlertController - cover older handling of UIAlertview and UIActionsheet.
Create new controller, which is dedicated from UIAlertController, where you must overloaded methods viewWillAppear and viewWillDisappear, like in example bellow.
AlertViewController.h
#import <UIKit/UIKit.h>
#interface AlertViewController : UIAlertController
#end
AlertViewController.m
#import "AlertViewController.h"
#interface AlertViewController ()
#end
#implementation AlertViewController
- (void) viewWillAppear:(BOOL)animated {
[self.view setTransform:CGAffineTransformMakeRotation(M_PI_2)];
}
- (void) viewWillDisappear:(BOOL)animated {
[self.view setHidden:YES];
}
...
implement method for showing alert view where you needed.
(void) showInfoAlertView {
AlertViewController *alert = [AlertViewController alertControllerWithTitle:#"My Alert" message:#"This is an alert." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:ok];
[self presentViewController:alert animated:NO completion:nil];
}