**********************更新:问题已经解决!! 不回复。谢谢! :)
我正在尝试为名为RootViewController的UIViewController实现多个方向。它是应用程序中的根视图控制器。
我按照Apple教程(https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDeviceOrientationChanges/RespondingtoDeviceOrientationChanges.html)中的说明操作,并在RootViewController类中实现以下代码:
- (void) viewDidLoad {
...
// detect orientation changed
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
....
}
- (void) orientationChanged:(NSNotification *)note {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
log(@"self: %@, orientation: %d", self, (int)orientation);
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView) {
log(@"show landscape view");
[self performSegueWithIdentifier:@"go_landscape" sender:self];
isShowingLandscapeView = YES;
} else if (UIDeviceOrientationIsPortrait(deviceOrientation) && isShowingLandscapeView) {
log(@"show portrait view");
[self dismissViewControllerAnimated:NO completion:nil];
isShowingLandscapeView = NO;
}
}
当我尝试将模拟器旋转到横向模式时,会调用orientationChanged方法。但是当我将其旋转回来时,我看到一个非常奇怪的情况:RootViewController获得一个重复的实例(原始实例id = 0x7fc4eb813a00,并且在下面的日志中重复的一个是0x7fc4eb081800)。
-[RootViewController orientationChanged:] [Line 796] self: <RootViewController:
0x7fc4eb813a00>, orientation: 1
-[RootViewController orientationChanged:] [Line 796] self: <RootViewController:
0x7fc4eb813a00>, orientation: 3
-[RootViewController orientationChanged:] [Line 800] show landscape view
-[RootViewController orientationChanged:] [Line 796] self: <RootViewController:
0x7fc4eb813a00>, orientation: 1
-[RootViewController orientationChanged:] [Line 804] show portrait view
-[RootViewController orientationChanged:] [Line 796] self: <RootViewController:
0x7fc4eb081800>, orientation: 1
如果我再次将其旋转到横向模式,应用程序将崩溃为以下日志。 (重复的那个没有segue。)
-[RootViewController orientationChanged:] [Line 796] self: <RootViewController:
0x7fc4eb081800>, orientation: 3
-[RootViewController orientationChanged:] [Line 800] show landscape view
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: 'Receiver (<RootViewController: 0x7fc4eb081800>) has no segue with
identifier 'go_landscape''
*** First throw call stack:
故事板:
segue设置:
我真的不知道为什么会这样。我创建了一个新项目来测试方向改变实现,不会发生奇怪的情况。有任何调查方向吗?
答案 0 :(得分:1)
当您切换到横向时,您已发布的代码是DESIGNED以创建新的视图控制器。 performSegue
方法创建一个新的视图控制器。这是它的工作原理。
我总是尽量避免创建一个新的视图控制器来支持不同的方向。相反,我设置代码来调整几何变化。我使用旧式调整大小的面具比使用AutoLayout更好,但是我使用了这两种方法。
答案 1 :(得分:0)
哦我的... performSegueWithIdentifier方法确实创建了另一个实例,即使它是同一个类。我找到了应用程序崩溃的根本原因。
在我的新项目中,当方向改变时,日志显示如下。当调用dismissViewControllerAnimated方法解除self时,新创建的实例将被释放。
self: <RootViewController: 0x7f99d1518890>, orientation: 3, isShowingLandscapeView: 0
show lanscape view
self: <RootViewController: 0x7f99d1518890>, orientation: 1, isShowingLandscapeView: 1
show portrait view
self: <RootViewController: 0x7f99d1727500>, orientation: 1, isShowingLandscapeView: 0
[RootViewController dealloc] [Line 35] !!!!!! dealloc instance: <RootViewController: 0x7f99d1727500>
但是,我的原始项目中的日志不会像上面那样显示...新创建的实例不是dealloc!所以它会崩溃,因为第二个实例是基于第二个故事UIViewController布局创建的,它不包含segue“go_landscape”。
self: <RootViewController: 0x7fc142818400>, orientation: 3, isShowingLandscapeView: 0
show landscape view
self: <RootViewController: 0x7fc142818400>, orientation: 1, isShowingLandscapeView: 1
show portrait view, self: <RootViewController: 0x7fc142818400>
self: <RootViewController: 0x7fc142200600>, orientation: 1, isShowingLandscapeView: 0
self: <RootViewController: 0x7fc142818400>, orientation: 3, isShowingLandscapeView: 0
show landscape view
self: <RootViewController: 0x7fc142200600>, orientation: 3, isShowingLandscapeView: 0
show landscape view
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<RootViewController: 0x7fc142200600>) has no segue with identifier 'go_landscape''
但为什么!???这两个项目都使用ARC机制并处理相同的代码。为什么新项目中的新实例将正常dealloc,但原始项目中的新实例将不会被dealloc!???????
必须解决此问题,否则在方向更改时会导致内存泄漏,因为它始终会创建新的垃圾实例。
答案 2 :(得分:0)
- (void) startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector(tick)
userInfo:nil
repeats:YES];
}