我的应用程序第一次启动时,我有一个用户注册屏幕,我在其中捕获姓名和电子邮件。
作为文本字段验证的一部分,如果验证失败,我会显示UIAlertController
。在我的保存按钮操作中调用此验证方法,此处也显示UIAlertController
。
当我关闭项目的大小类时,这工作正常。我现在已经更新了我的项目以使用Size Classes。从那时起,我一直在收到这个警告。
Warning: Attempt to present <UIAlertController: 0x7b074660> on <WelcomeViewController: 0x7b0428d0> whose view is not in the window hierarchy!
现在,如果我单击“保存”,则会移动到下一个屏幕而不显示警报。
以下是我上面描述的代码:
- (IBAction)save:(id)sender {
NSString *errorMessage = [self validateForm];
if (errorMessage) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Detail Missing" message:errorMessage preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {}];
[alert addAction:cancelAction];
[self presentViewController:alert animated:YES completion:nil];
return;
}
//Saving username and email in NSUSerDefaults
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
[userData setObject:self.userTextField.text forKey:@"UserName"];
[userData setObject:self.emailTextField.text forKey:@"Email"];
[userData setBool:YES forKey:@"UserReg"]; }
- (NSString *)validateForm {
NSString *errorMessage;
if (![self.userTextField.text isValidText]){
errorMessage = @"Please enter your name";
} else if (![self.emailTextField.text isValidEmail]){
errorMessage = @"Please enter a valid email address";
}
return errorMessage;
}
在AppDelegate.m
中,我会检查是否存储了用户信息。如果还没有,我的欢迎屏幕会显示(我捕获详细信息),否则我会加载主应用程序屏幕。
如果我第一次正确输入用户详细信息并按保存,则应用程序正常运行,没有任何问题。
我已经找到了类似问题的答案,遗憾的是他们没有帮助我,因为我的UIAlertController在保存按钮操作中被调用,而不是viewDidLoad
或viewDidAppear
或viewWillAppear
。
我该怎么做才能解决这个问题?
Rob的回复附加信息
我已经尝试过Rob建议的两种方法 - 我只是查找视图控制器的视图地址,其他我将UIView子类化并将标记分配给WelcomeViewController的根视图。两个结果都是相似的,因为我可以在层次结构中找到我的视图。
以下是使用子类和标记的结果:
<WelcomeViewController 0x78ea7850>, state: appeared, view: <WelcomeView 0x78e7b210>
+ <UINavigationController 0x78e58c00>, state: disappeared, view: <UILayoutContainerView 0x78e5bcb0> not in the window, presented with: <_UIFullscreenPresentationController 0x78ef3ac0>
| | <WardrobeListTableViewController 0x78ef3940>, state: disappeared, view: <UITableView 0x7a357600> not in the window
递归层次结构
<UIWindow: 0x799ad460; frame = (0 0; 320 568); gestureRecognizers = <NSArray: 0x799adac0>; layer = <UIWindowLayer: 0x799acfe0>>
| <WelcomeView: 0x78e7b210; frame = (0 0; 320 568); autoresize = W+H; tag = 10; layer = <CALayer: 0x78e7b0c0>>
| | <UINavigationBar: 0x78e7aed0; frame = (0 20; 320 44); opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x78e6fb60>; layer = <CALayer: 0x78e7ade0>>
| | | <_UINavigationBarBackground: 0x78e70bd0; frame = (0 0; 320 44); userInteractionEnabled = NO; layer = <CALayer: 0x78e70d90>>
| | | | <_UIBackdropView: 0x78e5df70; frame = (0 0; 320 44); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <_UIBackdropViewLayer: 0x78e59050>>
| | | | | <_UIBackdropEffectView: 0x78e58620; frame = (0 0; 320 44); clipsToBounds = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; animations = { filters.colorMatrix.inputColorMatrix=<CABasicAnimation: 0x799b3730>; }; layer = <CABackdropLayer: 0x78e582b0>>
| | | | | <UIView: 0x78e57b40; frame = (0 0; 320 44); hidden = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x78e57b10>>
| | | | <UIImageView: 0x78e706b0; frame = (0 44; 320 0.5); userInteractionEnabled = NO; layer = <CALayer: 0x78e70580>>
| | | <UINavigationItemView: 0x78e74390; frame = (91.5 8; 137 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x78e74260>>
| | | | <UILabel: 0x78e74060; frame = (0 3.5; 137 21.5); text = 'User Registration'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x78e73f30>>
| | | <_UINavigationBarBackIndicatorView: 0x799b6a00; frame = (8 11.5; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x799b6ba0>>
| | <UITextView: 0x79373400; frame = (0 64; 320 90); text = 'Welcome to the Baby Wardr...'; clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x78e6dfb0>; layer = <CALayer: 0x78e6fa00>; contentOffset: {0, 0}; contentSize: {320, 88}>
| | | <<_UITextContainerView: 0x78e6c9c0; frame = (0 0; 320 88); layer = <_UITextTiledLayer: 0x78e6cca0>> minSize = {320, 0}, maxSize = {3.4028235e+38, 3.4028235e+38}, textContainer = <NSTextContainer: 0x79886290 size = (320.000000,340282346638528859811704183484516925440.000000); widthTracksTextView = YES; heightTracksTextView = NO>; exclusionPaths = 0x0; lineBreakMode = 0>
| | | | <_UITileLayer: 0x78e4fab0> (layer)
| | | | <_UITileLayer: 0x78e54860> (layer)
| | | | <_UITileLayer: 0x78e656e0> (layer)
| | | | <_UITileLayer: 0x78e5a060> (layer)
| | | | <UITextSelectionView: 0x78e63900; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x78e637b0>>
| | | <UIImageView: 0x799b7090; frame = (0 87.5; 600 2.5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x799b7110>>
| | | <UIImageView: 0x799b74e0; frame = (317.5 8; 2.5 82); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x799b7560>>
| | <UITextField: 0x78e7e2a0; frame = (16 174; 288 30); text = ''; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x79996a90>; layer = <CALayer: 0x78e7e3e0>>
| | | <_UITextFieldRoundedRectBackgroundViewNeue: 0x78e7b600; frame = (0 0; 288 30); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x78e7b5d0>>
| | | <UITextFieldLabel: 0x78e7b820; frame = (7 1; 274 27); text = 'Name'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x78e7b7d0>>
| | <UITextField: 0x78efbec0; frame = (16 214; 288 30); text = ''; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x799ae7c0>; layer = <CALayer: 0x78e7f420>>
| | | <_UITextFieldRoundedRectBackgroundViewNeue: 0x78e7cea0; frame = (0 0; 288 30); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x78e7d080>>
| | | <UITextFieldLabel: 0x78e7bef0; frame = (7 1; 274 27); text = 'Email Address'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x78e7c0f0>>
| | <UIButton: 0x799ae9b0; frame = (80 264; 160 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x799aebb0>>
| | | <UIButtonLabel: 0x78e5e460; frame = (25 6; 109.5 18); text = 'Save & Proceed'; alpha = 0.2; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x78e5e0f0>>
| | <_UILayoutGuide: 0x78e73db0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x78e73e70>>
| | <_UILayoutGuide: 0x78e66ea0; frame = (0 568; 0 0); hidden = YES; layer = <CALayer: 0x78e7cb10>>
有关如何解决此问题的任何进一步建议?
Kiddae 的其他信息 正如我所提到的,我在AppDelegate.m中执行检查以决定要显示哪个viewController。这是代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
//Check if user data has been saved & determine the initial view controller
NSString *identifier;
BOOL isSaved = [[NSUserDefaults standardUserDefaults] boolForKey:@"UserReg"];
if (isSaved)
{
identifier=@"Wardrobe";
}
else
{
identifier=@"Welcome";
}
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:identifier];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
答案 0 :(得分:0)
如果视图控制器层次结构因任何原因与视图层次结构不同步,则会出现此错误。运行应用程序并暂停执行(但不要停止它)或在代码中添加断点。如果您在iOS 8或更高版本上运行此操作,则在(lldb)
提示符下,您可以检查_printHierarchy
结果,如下所示:
(lldb) po [[[UIWindow keyWindow] rootViewController] _printHierarchy] <UINavigationController 0x7fef00d3dc10>, state: appeared, view: <UILayoutContainerView 0x7fef02b63550> | <myapp.ViewController 0x7fef00d348b0>, state: appeared, view: <UIView 0x7fef00e43950> | | <myapp.WelcomeViewController 0x7fef02b12290>, state: appeared, view: <UIView 0x7fef02b6b520>
确保该视图控制器层次结构中出现WelcomeViewController
。
您还可以使用recursiveDescription
确认视图层次结构:
(lldb) po [[UIWindow keyWindow] recursiveDescription] <UIWindow: 0x7fa17a83a750; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fa17a823120>; layer = <UIWindowLayer: 0x7fa17a8241e0>> | <UILayoutContainerView: 0x7fa178527a80; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa178578c20>; layer = <CALayer: 0x7fa178634dc0>> | | <UINavigationTransitionView: 0x7fa17863b5c0; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7fa17863b6d0>> | | | <UIViewControllerWrapperView: 0x7fa178647570; frame = (0 0; 375 667); autoresize = RM+BM; layer = <CALayer: 0x7fa178647640>> | | | | <UIView: 0x7fa1786480d0; frame = (0 0; 375 667); autoresize = RM+BM; layer = <CALayer: 0x7fa1786473d0>> | | | | | <_UILayoutGuide: 0x7fa1786481a0; frame = (0 0; 0 64); hidden = YES; layer = <CALayer: 0x7fa1786470d0>> | | | | | <_UILayoutGuide: 0x7fa178648b00; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x7fa178647660>> | | | | | <UIView: 0x7fef02b6b520; frame = (0 0; 375 667); autoresize = W+H; tag = 1; layer = <CALayer: 0x7fa178426c60>> | | | | | | <UIButton: 0x7fa1784260b0; frame = (309 629; 46 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x7fa1784254b0>> | | | | | | | <UIButtonLabel: 0x7fa17842b1b0; frame = (0 6; 46 18); text = 'Button'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fa17842b520>> | | | | | | <_UILayoutGuide: 0x7fa178426d50; frame = (0 0; 0 64); hidden = YES; layer = <CALayer: 0x7fa178426e30>> | | | | | | <_UILayoutGuide: 0x7fa178426fa0; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x7fa1784255e0>> | | <UINavigationBar: 0x7fa17a8309a0; frame = (0 20; 375 44); opaque = NO; autoresize = W; gestureRecognizers = ; layer = <CALayer: 0x7fa17a826020>> | | | <_UINavigationBarBackground: 0x7fa17a83a9f0; frame = (0 -20; 375 64); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fa17a834ca0>> | | | | <_UIBackdropView: 0x7fa1785796e0; frame = (0 0; 375 64); opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <_UIBackdropViewLayer: 0x7fa17863f2d0>> | | | | | <_UIBackdropEffectView: 0x7fa1786404e0; frame = (0 0; 375 64); clipsToBounds = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CABackdropLayer: 0x7fa178640bc0>> | | | | | <UIView: 0x7fa178641a30; frame = (0 0; 375 64); hidden = YES; opaque = NO; autoresize = W+H; userInteractionEnabled = NO; layer = <CALayer: 0x7fa178641b00>> | | | | <UIImageView: 0x7fa17a83b0b0; frame = (0 64; 375 0.5); userInteractionEnabled = NO; layer = <CALayer: 0x7fa17a825e20>> | | | <UINavigationButton: 0x7fa17a832fd0; frame = (333 8; 34 30); opaque = NO; layer = <CALayer: 0x7fa17a8329d0>> | | | | <UIButtonLabel: 0x7fa17a835e10; frame = (0 4; 34 20.5); text = 'Item'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fa17a8362c0>> | | | <_UINavigationBarBackIndicatorView: 0x7fa178638f90; frame = (8 11.5; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fa1786392d0>>
此视图层次结构有时难以遵循,因此您可能希望:
为tag
的根view
指定非零WelcomeViewController
(因为recursiveDescription
将显示非零标记号)。这就是我上面所做的(我突出显示了这条线,这样你就可以很快看到它,这显然不会为你做什么)。
子类UIView
并指定它作为WelcomeViewController
视图的基类(注意,这个UIView
子类不需要做任何事情,我们只想要一个不同的类,所以你可以在recursiveDescription
输出中区分它。或者,
从视图控制器层次结构中标识视图控制器的视图地址(我的示例中为0x7fef02b6b520
),并在视图层次结构中查找该视图。
这些技术中的任何一种都可以帮助您识别特定视图控制器的视图是否在层次结构中。