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

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];
}
}];
}

Related

ios7 - how to transition back to self

as per the following storyboard, I have a RootViewController (embedded in a TabBarController), which manage many ViewControllers with a vertical menu.
When this RootViewController did load, I check for client authentication, and if not yet authenticated, I switch to a ConnectViewController for remote authentication
#implementation WDURootViewController
....
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
if (!self.client.isAuthorized) {
WDUConnectViewController *cvc = self.connectVC;
[self addChildViewController:cvc];
[self.view addSubview:cvc.view];
[cvc didMoveToParentViewController:self];
}
}
when authentication is successful, I want to come back to the RootViewController...
so in my ConnectViewController, I call back a didConnect() method to notify the RootViewController
#implementation WDUConnectViewController
....
- (IBAction)sendGrantRequest
{
....
[self.client authorizeUser:login password:pwd
onSuccess:^() {
[self.workinOnIt stopAnimating];
[self.connectButton setEnabled:YES];
[(WDURootViewController *)self.parentViewController didConnect];
}
and in the RootViewController, didConnect() method I try to switch the views, in transition from the ConnectViewController to the RootViewController
#implementation WDURootViewController
....
- (void)didConnect
{
[self transitionFrom:self.connectVC To:self];
}
....
- (void)transitionFrom:(UIViewController *)oldC To:(UIViewController *)newC
{
[oldC willMoveToParentViewController:nil];
[self addChildViewController:newC];
[self transitionFromViewController: oldC toViewController: newC
duration: 0.25 options:0
animations: nil
completion:^(BOOL finished) {
[oldC removeFromParentViewController];
[newC didMoveToParentViewController:self];
}];
}
- (WDUConnectViewController *)connectVC {
if (_connectVC == nil) {
UIStoryboard *storyboard = self.storyboard;
_connectVC = [storyboard instantiateViewControllerWithIdentifier:#"WDUConnectViewController"];
_connectVC.client = self.client;
}
return _connectVC;
}
but the transition method is looping... I guess it's not the way to go , what's the simplest way?
I got it , just updating the didConnect() method in the RootViewController
- (void)didConnect
{
[self.connectVC willMoveToParentViewController:nil];
[self.connectVC.view removeFromSuperview];
[self.connectVC removeFromParentViewController];
[self awakeFromNib];
}

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 to change speed of segue between ViewControllers

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!

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];
}