我知道这是一个常见问题,但似乎无法找到符合我需求的正确解决方案。
好的,我有一个 UIViewController (哪个父视图是 UINavigationController ,然后是 UITabBarController )被强制进入肖像模式。这个人能够以模态方式呈现另一个 UIViewController ,当用户旋转设备时,该 UIViewController 被强制保持在横向模式。我决定用一个手动的segue来介绍这个最后一个人。 以下是演示文稿的代码:
- (void)viewDidAppear:(BOOL)animated {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)orientationChanged:(NSNotification *)notification {
// Respond to changes in device orientation
if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) {
[self performSegueWithIdentifier:@"gallerySegue" sender:self];
}
}
-(void) viewDidDisappear {
// Request to stop receiving accelerometer events and turn off accelerometer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
要返回第一个视图控制器,我使用这些代码
- (void)viewDidAppear:(BOOL)animated {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(returnBack:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
-(void) viewDidDisappear {
// Request to stop receiving accelerometer events and turn off accelerometer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
- (void)returnBack:(NSNotification *)notification {
// Respond to changes in device orientation
if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {
[self dismissViewControllerAnimated:NO completion:nil];
}
}
当我旋转设备时,第二个视图控制器会生成警告。
WHY ??
由于
答案 0 :(得分:1)
Warning: Attempt to present ViewController on TabBarController whose view is not in the window hierarchy
。此警告是因为当您从viewController中push:
或present:
viewController
时不在视图中。含义您的第一个视图控制器尚未加载或完全显示,但是您正在呈现或推送另一个视图控制器。
答案 1 :(得分:0)
解决!
而不是这个
- (void)viewDidAppear:(BOOL)animated {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
我将上面的代码放在viewWillAppear中。
关于这个
-(void) viewDidDisappear {
// Request to stop receiving accelerometer events and turn off accelerometer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
我将它放在prepareForSegue方法中并且有效!
答案 2 :(得分:0)
我是一位快速用户,但我认为在这里值得一提:
如果您尝试在viewDidLoad()
上执行UI任务,则会收到此消息,因为您正在执行的所有任务都将加载到内存中,但在正确加载视图层次结构之前无法执行任何操作。只是您在尝试查看层次结构之前正在尝试做某事。
因此,解决方案是等待几秒钟,直到正确加载视图层次结构。这是不建议使用的方法(也将在显示视图后执行),但我需要向您展示您也可以执行以下操作:
override func viewDidLoad() {
super.viewDidLoad()
//your stuff....
Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(doSomeStuff), userInfo: nil, repeats: false)
}
@objc func doSomeStuff() {
//your stuff....
self.performSegue(withIdentifier: "signInTabBarVC", sender: nil) // i just want to perform transition if logged in
}
正如我所说的那样,不建议这样做,这是建议的方法:
override func viewDidAppear(_ animated: Bool) {
//if Auth.auth().currentUser != nil {
self.performSegue(withIdentifier: "signInTabBarVC", sender: nil)
//}
}
上面是override
方法,苹果公司推荐该方法执行UI任务。因为它是在视图层次结构初始化并附加后执行的。