Animation between two UIViewController when I do makeKeyAndVisible - cocoa-touch

I'm trying to do an animation to switch between two UIViewController that I have. But when the animation runs, the old UIViewController is white.
// viewController is the new UIViewController
[UIView animateWithDuration:0.6
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^(void){
[viewController.view setTransform:CGAffineTransformMakeTranslation(0, -460)];
}
completion:^(BOOL finished){
if (finished){
//
}
}
];
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:viewController];
[[[[UIApplication sharedApplication] delegate] window] makeKeyAndVisible];
I have an object which always has the UIViewController:
#interface ManagerViews : NSObject {
UIViewController *oneController;
UIViewController *twoController;
...
}
#property(nonatomic, retain) UIViewController *oneController;
#property(nonatomic, retain) UIViewController *twoController;
...
What am I doing wrong?

Have you tried to set the old UIViewController to "nil" or (my Objective-C expertise is a little rusty) reset?

Related

Impossible to presentViewController

I've created a new application view based.
Here some the main code:
// AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UINavigationController *navigationController;
MIAPreferences *preferences;
}
#property (strong, nonatomic) UINavigationController *navigationController;
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) MIAPreferences *preferences;
// AppDelegate.m
#implementation AppDelegate
#synthesize window = _window;
#synthesize navigationController;
#synthesize preferences;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
// Override point for customization after application launch.
UIViewController *rootController = [[HomeViewController alloc] initWithNibName:nil bundle:nil];
navigationController = [[UINavigationController alloc]
initWithRootViewController:rootController];
navigationController.navigationBar.hidden = YES;
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
_window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
// HomeViewController.m
-(IBAction)openLogin
{
LoginViewController *view = [[LoginViewController alloc] initWithNibName:nil bundle:nil];
// 1
[self.navigationController presentViewController:view animated:YES completion:nil];
// 2
[self.navigationController pushViewController:view animated:YES];
// 3
[self presentViewController:view animated:YES completion:nil];
}
All 3 options returns a EXC_BAD_ACCESS (code=2, address=....)
Can you please help me understand how to solve this?
UPDATE
The problem was due to a UIButton apparence set up during AddDelegate loading....but the first button was in the UIView I was going to load... that's why it crashed -.-"
It could either mean: (1) The pointer used to point to memory that was ok, but its chunk was deallocated or (2) The pointer is corrupt. You can try to use zombie mode, if you aren't already, to get more information. In XCode press the Command, option, and I keys and a screen should pop up. Selected the Run option in the left hand side, then Diagnostics, and under memory management enable zombie objects should be checked.
Check the value of view after initWithNibName:. init'ing with a nil nib name looks wrong to me, and you may be trying to push a nil view controller onto your navigation stack.

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!

iAd Banner View Delegate Not Calling Methods

I have an iAd banner view, with all my contracts up and running, and I've implemented the ADBannerView delegate. The banner should disappear with no internet connection, but it just shows a white box where the content should be. I know I have all the code right, I've seen a million tutorials on this. So I ran some tests and found that the banner view wasn't even calling the two methods for the delegate! Here is the code.
In the .h file:
#import <iAd/iAd.h>
#interface DetailViewController : ADBannerViewDelegate>
{
ADBannerView *aBanner;
BOOL bannerIsVisible;
}
#property (nonatomic, retain) IBOutlet ADBannerView *aBanner;
#property (nonatomic, assign) BOOL bannerIsVisible;
#end
in the .m file:
#implementation DetailViewController
#synthesize aBanner,bannerIsVisible;
//Show banner if can load ad.
-(void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!self.bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOn" context:NULL]; banner.frame = CGRectOffset(banner.frame, 0, -banner.frame.size.height);
[UIView commitAnimations]; self.bannerIsVisible = YES; }
}
//Hide banner if can't load ad.
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOff" context:NULL]; banner.frame = CGRectOffset(banner.frame, 0, banner.frame.size.height);
[UIView commitAnimations]; self.bannerIsVisible = NO; }
}
You have to set the banner delegate to files owner. I had the same issue and after beating my head against the wall it was that simple.
Use the code shown below to declare your own delegate
-(void)viewDidLoad {
aBanner.delegate = self;
}

How do I call a method every x seconds?

I have a NSWindow that I'm putting into fullscreen mode. I would like to be able to hide the mouse when its not in use (say 15 seconds after it was last used). I have my application delegate as follows:
MyMediaRoomAppDelegate.h:
#import <Cocoa/Cocoa.h>
#interface MyMediaRoomAppDelegate : NSResponder <NSApplicationDelegate> {
NSWindow *window;
NSDate *lastMouseMove;
}
#property (assign) IBOutlet NSWindow *window;
#property (nonatomic, retain) NSDate *lastMouseMove;
#end
MyMediaRoomAppDelegate.m:
#import "MyMediaRoomAppDelegate.h"
#implementation MyMediaRoomAppDelegate
#synthesize window;
#synthesize lastMouseMove;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// The application has just finished lanching
// Grab the screen size
NSRect screenRect;
screenRect = [[NSScreen mainScreen] frame];
// Setup the window - full screen
[[self window] setLevel:NSMainMenuWindowLevel+1];
[[self window] setStyleMask:NSBorderlessWindowMask];
[[self window] setOpaque:YES];
[[self window] setBackgroundColor:[NSColor blackColor]];
[[self window] setFrame:screenRect display:YES animate:NO];
// Setup the mouse
[[self window] setAcceptsMouseMovedEvents:YES];
[[self window] makeFirstResponder:self];
[NSCursor hide];
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (void)mouseMoved:(NSEvent *)theEvent
{
[NSCursor unhide];
[self setLastMouseMove: [NSDate date]];
}
#end
What I'm not sure about is how to re-hide the cursor after 15 seconds. The thing is I need to check setLastMouseMove, every second or so, not just call [NSCursor hide] after 15 seconds is up.
Try NSTimer. You can specify it to be repeating at creation time.