开发者

How can the subView detect that the mainView is rotating?

I have a mainView. To this view, I am adding a view of the same size. When the mainView(the background) rotates, its being detected but the subview doesnt have any idea about being rotated. And its functions are not even being called. Even when the program launches too, if I am in landscape mode, its the same way.

How can I make the 开发者_开发技巧subView know that the device is being rotated?


Perhaps you can shoot an event from the mainView to the subView, like so (in mainView):

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    [subView didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}


I quickly grew frustrated by the lack of rotation notification support for non-primary UIViewController instances.

So I baked my own as a UIViewController extension. Note that this is purely for rotation detection within the subview, it won't rotate the subview - I'm working on that part now.

Source code then example usage below.

// Released under license GPLv3.
// Copyright (c) 2012 N David Brown. All Rights Reserved.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

// Note: 'shouldAutorotateToInterfaceOrientation:' is automatically called by
//       'willRotate..', 'didRotate..' method calling notification handler
//       blocks, so typically will not be desired for notification.
#define NOTIFY_SHOULD_AUTOROTATE 0
@interface UIViewController (NDBExtensions)
    // For dispatchers.
#if NOTIFY_SHOULD_AUTOROTATE
    -(void)notifyShouldAutorotate:(UIInterfaceOrientation)toInterfaceOrientation;
#endif
    -(void)notifyWillRotate:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
    -(void)notifyDidRotate:(UIInterfaceOrientation)fromInterfaceOrientation;
    // For listeners.
#if NOTIFY_SHOULD_AUTOROTATE
    -(void)listenForShouldAutorotate;
#endif
    -(void)listenForWillRotate;
    -(void)listenForDidRotate;
    -(void)listenForAnyRotate;
    -(void)stopListeningForAnyRotate;
    @end

@implementation UIViewController (NDBExtensions)

#if NOTIFY_SHOULD_AUTOROTATE
    -(void)notifyShouldAutorotate:(UIInterfaceOrientation)toInterfaceOrientation {
        NSString *name = @"shouldAutorotate";
        NSString *key = @"toInterfaceOrientation";
        NSNumber *val = [NSNumber numberWithInt:toInterfaceOrientation];
        NSDictionary *info = [NSDictionary dictionaryWithObject:val forKey:key];
        [[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:info];
    }
#endif

-(void)notifyWillRotate:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    NSString *name = @"willRotate";
    NSString *key = @"toInterfaceOrientation";
    NSNumber *val = [NSNumber numberWithInt:toInterfaceOrientation];
    NSString *key2 = @"duration";
    NSNumber *val2 = [NSNumber numberWithDouble:duration];
    NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:val,key,val2,key2,nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:info];
}

-(void)notifyDidRotate:(UIInterfaceOrientation)fromInterfaceOrientation {
    NSString *name = @"didRotate";
    NSString *key = @"fromInterfaceOrientation";
    NSNumber *val = [NSNumber numberWithInt:fromInterfaceOrientation];
    NSDictionary *info = [NSDictionary dictionaryWithObject:val forKey:key];
    [[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:info];
}

#if NOTIFY_SHOULD_AUTOROTATE
-(void)listenForShouldAutorotate {
    [[NSNotificationCenter defaultCenter]
        addObserverForName:@"shouldAutorotate"
        object:nil queue:nil
        usingBlock:^(NSNotification* notification){
            NSNumber *val = [[notification userInfo] objectForKey:@"toInterfaceOrientation"];
            UIInterfaceOrientation toInterfaceOrientation = (UIInterfaceOrientation)[val intValue];
            [self shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
        }];
}
#endif

-(void)listenForWillRotate {
    [[NSNotificationCenter defaultCenter]
        addObserverForName:@"willRotate"
        object:nil queue:nil
        usingBlock:^(NSNotification* notification){
            NSNumber *val = [[notification userInfo] objectForKey:@"toInterfaceOrientation"];
            UIInterfaceOrientation toInterfaceOrientation = (UIInterfaceOrientation)[val intValue];
            NSNumber *val2 = [[notification userInfo] objectForKey:@"duration"];
            NSTimeInterval duration = [val2 doubleValue];
            if ([self shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]) {
                [self willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
            }
        }];
}

-(void)listenForDidRotate {
    [[NSNotificationCenter defaultCenter]
        addObserverForName:@"didRotate"
        object:nil queue:nil
        usingBlock:^(NSNotification* notification){
            NSNumber *val = [[notification userInfo] objectForKey:@"fromInterfaceOrientation"];
            UIInterfaceOrientation fromInterfaceOrientation
                = (UIInterfaceOrientation)[val intValue];
            UIInterfaceOrientation toInterfaceOrientation
                = (UIInterfaceOrientation)[[UIDevice currentDevice] orientation];
            if ([self shouldAutorotateToInterfaceOrientation:toInterfaceOrientation]) {
                [self didRotateFromInterfaceOrientation:fromInterfaceOrientation];
            }
        }];
}

-(void)listenForAnyRotate {
#if NOTIFY_SHOULD_AUTOROTATE
    [self listenForShouldAutorotate];
#endif
    [self listenForWillRotate];
    [self listenForDidRotate];
}

-(void)stopListeningForAnyRotate {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"shouldAutorotate" object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"willRotate" object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"didRotate" object:nil];
}
@end

Example usage:

// In PrimaryViewController.h (instance of this contains 'view'
// which is first subview in window).

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    // Normal rules go here.
    return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
    // Normal rules go here.
    // ..and notification dispatch:
    [self notifyWillRotate:toInterfaceOrientation duration:duration];
}

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    // Normal rules go here.
    // ..and notification dispatch:
    [self notifyDidRotate:fromInterfaceOrientation];
}


// In OtherViewController.h (this could be any non-primary view controller).

-(void)viewDidLoad {
    [self listenForAnyRotate];
}

-(void)viewDidUnload {
    [self stopListeningForAnyRotate];
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    // Normal rules go here.
    return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
    // Normal rules go here.
    NSLog(@"#willRotate received!");
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    // Normal rules go here.
    NSLog(@"#didRotate received!");
}


You could fire an NSNotification when the main view is rotated, which the subview is registered to listen for. There's a quick overview of NSNotification over here.

One advantage of this approach is that objects other than subclasses of UIView can listen for this notification.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜