【问题标题】:View controller not getting -shouldAutorotateToInterfaceOrientation: messages on second load?视图控制器没有收到 -shouldAutorotateToInterfaceOrientation:第二次加载时的消息?
【发布时间】:2010-12-02 18:31:54
【问题描述】:

我有一个UIViewController,我用它来控制一个“弹出”视图,以便在整个应用程序中查看图像。它支持自动旋转,因为它会自动调整图像大小以适合任何方向。这工作得很好,但只是我第一次初始化和显示视图控制器。当它关闭时,我将从视图层次结构中删除 UIView 并释放视图控制器 - 但下次我实例化并将其添加到我的视图层次结构时,它会在手机旋转时停止接收 -shouldAutorotateToInterfaceOrientation 消息。

这是我实例化和显示它的方式:

popupVC = [[PopupVC alloc] init];
[popupVC viewWillAppear:NO];
[[[UIApplication sharedApplication] keyWindow] addSubview:popupVC.view];
[popupVC viewDidAppear:NO];

这是我在完成后删除/释放它的方式:

[popupVC viewWillDisappear:NO];
[popupVC.view removeFromSuperview];
[popupVC viewDidDisappear:NO];
[popupVC release];
popupVC = nil;

我尝试循环遍历[[UIApplication sharedApplication] keyWindow] 子视图以查看我的弹出视图是否以某种方式不在顶部,但它总是如此。而且它每次都有不同的地址,所以我知道它是视图控制器类的不同实例。

根据要求,这是来自PopupVC 的完整loadView 方法:

- (void)loadView {

    UIView *myView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    myView.backgroundColor = self.overlayColor;
    myView.autoresizesSubviews = NO;
    myView.hidden = YES;
    myView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    self.view = myView;
    [myView release];

    _isVisible = NO;

    UIView *myMaskView = [[UIView alloc] initWithFrame:self.view.bounds];
    myMaskView.backgroundColor = [UIColor clearColor];
    myMaskView.clipsToBounds = YES;
    myMaskView.hidden = YES;
    myMaskView.autoresizesSubviews = NO;
    myMaskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:myMaskView];
    self.imageMaskView = myMaskView;
    [myMaskView release];

    UIImageView *myImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
    myImageView.center = self.view.center;
    myImageView.hidden = NO;
    myImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
    [self.imageMaskView addSubview:myImageView];
    self.imageView = myImageView;
    [myImageView release];

    UIButton *myImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
    myImageButton.frame = self.view.frame;
    myImageButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
    [myImageButton addTarget:self action:@selector(clickImage:) forControlEvents:UIControlEventTouchUpInside];
    [self.imageMaskView addSubview:myImageButton];
    self.imageButton = myImageButton;

    UIActivityIndicatorView *myActivityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    myActivityView.hidden = YES;
    [self.view addSubview:myActivityView];
    myActivityView.center = self.view.center;
    self.activityView = myActivityView;
    [myActivityView release];
}

【问题讨论】:

  • 什么时候设置视图控制器?另外,我认为您不需要明确调用viewWillAppear:,除非重点是防止动画。
  • 当用户选择要显示的图像时,我以UITableViewDelegate 方法设置它。我的PopupVC -loadView 方法设置了它使用的视图和子视图。在发现我的UITabBarController 无法正常工作后,我养成了明确调用-viewWillAppear: 的习惯,除非您向他们发送消息。我猜这只是一种习惯。
  • 您不应该自己调用那些 viewWillAppear/viewDidAppear 方法。我认为您需要重新考虑如何初始化和清理弹出式 VC。

标签: iphone uiviewcontroller rotation


【解决方案1】:

shouldAutorotateToInterfaceOrientation 处理程序不是自定义代码响应旋转事件的地方。它的目的只是告诉操作系统您的视图控制器可以旋转。如果您想使用自定义代码来处理您应该覆盖的旋转事件 - didRotateFromInterfaceOrientation 或其他类似的回调方法之一,具体取决于您的需要:

  • willRotateToInterfaceOrientation:duration:
  • willAnimateRotationToInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:
  • willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
  • didAnimateFirstHalfOfRotationToInterfaceOrientation:
  • willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:

请参阅开发者文档中的 Autorotating Views

【讨论】:

  • 好点 - 虽然我没有在这里响应事件,但我以错误的方式调试它。感谢您指出这一点。
  • 虽然现在我看起来确实在-didRotateFromInterfaceOrientation: 中有一些调试代码并且它也没有被触发。
  • 尝试让您的视图控制器覆盖canBecomeFirstResponder 以返回YES,在viewDidAppear:animated 中执行[self becomeFirstResponder] 并在viewWillDisappear:animated 中执行相应的[self resignFirstResponder]。这有什么区别吗?
  • 遗憾的是,我的视图控制器永远不会收到-canBecomeFirstResponder:。 (但听起来很有希望!)
  • 您的视图控制器视图是如何创建的?你能分享一下你的 PopupVC 的 loadView 方法中的代码吗?此外,您的视图是否拥有整个屏幕,还是某种模式弹出窗口覆盖了其他视图?
【解决方案2】:

我认为这可能是新 OS 3.0 中的一个错误。解决方法是在打开 beginGeneratingDeviceOrientationNotifications 后使用 NSNotificationCenter。

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

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

-(void) receivedRotate: (NSNotification *) notification {
    DebugLog(@"ORIENTATION CHANGE");

    UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];

        if(interfaceOrientation == UIDeviceOrientationPortrait) {
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
            self.view.bounds = CGRectMake(0, 0, 320, 480);
        }
        else if(interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
            self.view.bounds = CGRectMake(0, 0, 480, 320);
        }
        else if(interfaceOrientation == UIDeviceOrientationLandscapeRight) {
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
            self.view.bounds = CGRectMake(0, 0, 480, 320);
        }
}

【讨论】:

  • #define degreesToRadians(x) (M_PI * (x) / 180.0)
【解决方案3】:

我的问题是我获得了 rootViewController 的旋转事件,但是一旦我启动我的第二个 viewController,除了运动(摇晃)和触摸之外,它不会收到任何信号。这和原帖是同一个问题吗——肯定是相似的??

我跟进了上述建议,但我没有正确编码选择器,因此一旦我尝试旋转它就会引发异常。同时,我在网上发现了另一个讨论,证实了这个问题是在 3.0.0 中引入的。 link text

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    相关资源
    最近更新 更多