didAnimateFirstHalfOfRotationToInterfaceOrientatio

2019-08-27 04:57发布

问题:

didAnimateFirstHalfOfRotationToInterfaceOrientation is deprecated in iOS 5.0. However I would like to use this method in my application. I am using the sample code that Apple offers in the iOS Dev Center, project name AlternateViews. I would like the app to rotate the portraitView while fading in the landscapeView. Can this be done in iOS 5 or is this feature forever gone?

portraitView currently calls:

[self presentModalViewController:self.landscapeViewController animated:YES];

while landscapeView calls this in code in the init method:

self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

It appears all of the animation is done in the following PortraitViewController.m:

#import "PortraitViewController.h"
#import "LandscapeViewController.h"

@implementation PortraitViewController

@synthesize landscapeViewController;

- (void)viewDidLoad
{
    self.view.backgroundColor = [UIColor colorWithRed:197.0/255.0 green:204.0/255.0 blue:211.0/255.0 alpha:1.0];

    LandscapeViewController *viewController = [[LandscapeViewController alloc]
                                                    initWithNibName:@"LandscapeView" bundle:nil];
    self.landscapeViewController = viewController;
    [viewController release];

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:)
                                                    name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void)viewDidUnload
{
    self.landscapeViewController = nil;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];

    [landscapeViewController release];

    [super dealloc];
}

- (void)orientationChanged:(NSNotification *)notification
{
    // We must add a delay here, otherwise we'll swap in the new view
    // too quickly and we'll get an animation glitch
    [self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0];
}

- (void)updateLandscapeView
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
    {
        [self presentModalViewController:self.landscapeViewController animated:YES];
        isShowingLandscapeView = YES;
    }
    else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
    {
        [self dismissModalViewControllerAnimated:YES];
        isShowingLandscapeView = NO;
    }    
}

// override to allow orientations other than the default portrait orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait); // support only portrait
}

@end

Here is my current implementation files which fail miserably. PortraitViewController.m:

#import "PortraitViewController.h"
#import "LandscapeViewController.h"

@implementation PortraitViewController

@synthesize landscapeViewController;

- (void)viewDidLoad
{   
    LandscapeViewController *viewController = [[LandscapeViewController alloc]
                                                    initWithNibName:@"LandscapeView" bundle:nil];
    self.landscapeViewController = viewController;
    [viewController release];
    NSLog(@"Portrait viewDidLoad");
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
}

- (void)viewDidUnload
{
    self.landscapeViewController = nil;
}

- (void)dealloc
{   
    [landscapeViewController release];

    [super dealloc];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
        NSLog(@"Portrait-willAnimateRotationToInterfaceOrientation Portrait");
    } else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSLog(@"Portrait-willAnimateRotationToInterfaceOrientation Landscape");
    }
    [self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0];

}

- (void)updateLandscapeView
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
    {
        NSLog(@"Portrait-present Landscape");
        [self presentModalViewController:self.landscapeViewController animated:YES];
        isShowingLandscapeView = YES;
    }
    else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
    {
        NSLog(@"Portrait-dismiss Landscape");
        [self dismissModalViewControllerAnimated:YES];
        isShowingLandscapeView = NO;
    }    
}

// override to allow orientations other than the default portrait orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
        return NO;
    else
        return YES;
}

@end

LandscapeViewController.m

#import "LandscapeViewController.h"

@implementation LandscapeViewController

// the designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
    {
        self.wantsFullScreenLayout = YES; // we want to overlap the status bar.

        // when presented, we want to display using a cross dissolve
        self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    }
    return self;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    oldStatusBarStyle = [[UIApplication sharedApplication] statusBarStyle];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
    NSLog(@"Landscape viewWillAppear");
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [[UIApplication sharedApplication] setStatusBarStyle:oldStatusBarStyle animated:NO];    
}

// override to allow orientations other than the default portrait orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // return YES for supported orientations
    if (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
        return NO;
    else
        return YES;
    //return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
        NSLog(@"Landscape-willAnimateRotationToInterfaceOrientation Portrait");
        [self dismissModalViewControllerAnimated:YES];
    } else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSLog(@"Landscape-willAnimateRotationToInterfaceOrientation Landscape");

    }
}


@end

回答1:

In Apple's UIViewController reference page, you'll find this useful paragraph in the "Handling View Rotations" section:

If you want to perform custom animations during an orientation change, you can do so in one of two ways. Orientation changes used to occur in two steps, with notifications occurring at the beginning, middle, and end points of the rotation. However, in iOS 3.0, support was added for performing orientation changes in one step. Using a one-step orientation change tends to be faster than the older two-step process and is generally recommended for any new code.

To add animations for an orientation change, override the willAnimateRotationToInterfaceOrientation:duration: method and perform your animations there.

Could you override the willAnimateRotationToInterfaceOrientation: method to do your animations?