警告-尝试在VC上显示UIAlertController



我的应用程序第一次启动时,我会在一个用户注册屏幕上捕获姓名和电子邮件。作为文本字段验证的一部分,如果验证失败,我将显示一个UIAlertController。此验证方法在我的"保存"按钮操作中调用,UIAlertController也显示在此处。

当我为我的项目关闭尺寸类时,这一切都很顺利。我现在已经更新了我的项目以使用尺寸类。从那以后,我一直收到这个警告。

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,而不是viewDidLoadviewDidAppearviewWillAppear

我能做些什么来解决这个问题?

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;
}

如果视图控制器层次结构由于任何原因与视图层次结构不同步,则可能会出现此错误。运行应用程序并暂停执行(但不要停止)或在代码中添加断点。如果您在iOS 8或更高版本上运行此程序,则可以在(lldb)提示符下检查_printHierarchy结果,如下所示:

(lldb)po[[UIWindow keyWindow]rootViewController]_printHierarchy]<UINavigationController 0x7fef00d3dc10>,状态:已出现,视图:<UI LayoutContainerView 0x7fef02b63550>|<myapp。ViewController 0x7fef00d348b0>,状态:已出现,视图:<UIView 0x7fef00e43950>|<myapp。WelcomeViewController 0x7fef02b12290>,状态:已出现,视图:<UIView 0x7fef02b6b520>

确保WelcomeViewController出现在该视图控制器层次结构中。

您还可以使用recursiveDescription:确认视图层次结构

(lldb)po[[UIWindow keyWindow]recursiveDescription]<UI窗口:0x7fa17a83a750;帧=(0;375 667);gestureRecognizers=<NSArray:0x7fa17a823120>;layer=<UIWindowLayer:0x7fa17a8241e0>>|<UI布局容器视图:0x7fa178527a80;帧=(0;375 667);autoresize=W+H;gestureRecognizers=<NSArray:0x7fa178578c20>;layer=<CA层:0x7fa178634dc0>>||<UI导航转换视图:0x7fa17863b5c0;帧=(0;375 667);clipseToBounds=是;autoresize=W+H;layer=<CAL层:0x7fa17863b6d0>>||<UIViewControllerWrapperView:0x7fa178647570;帧=(0;375 667);autoresize=RM+BM;layer=<CA层:0x7fa178647640>>|||<UI视图:0x7fa1786480d0;帧=(0;375 667);autoresize=RM+BM;layer=<CA层:0x7fa1786473d0>>||||&lt_UI布局指南:0x7fa1786481a0;帧=(0 0;0 64);hidden=YES;layer=<CA层:0x7fa1786470d0>>||||&lt_UI布局指南:0x7fa178648b00;帧=(0 667;0);hidden=YES;layer=<CA层:0x7fa178647660>|||<UI视图:0x7fef02b6b520;帧=(0;375 667);autoresize=W+H标签=1;layer=<CA层:0x7fa178426c60>>||||<UI按钮:0x7fa1784260b0;帧=(309 629;46 30);不透明=否;autoresize=RM+BM;layer=<CA层:0x7fa1784254b0>||||<UI按钮标签:0x7fa17842b1b0;帧=(0 6;46 18);text="按钮";不透明=否;userInteractionEnabled=NO;layer=&lt_UILabelLayer:0x7fa17842b520>>||||&lt_UI布局指南:0x7fa178426d50;帧=(0 0;0 64);hidden=YES;layer=<CA层:0x7fa178426e30>||||&lt_UI布局指南:0x7fa178426fa0;帧=(0 667;0);hidden=YES;layer=<CA层:0x7fa1784255e0>>||<UI导航栏:0x7fa17a8309a0;帧=(0 20;375 44);不透明=否;autoresize=W;gestureRecognizers=;layer=<CA层:0x7fa17a826020>>||&lt_UI导航栏背景:0x7fa17a83a9f0;帧=(0-20;375 64);autoresize=W;userInteractionEnabled=NO;layer=<CA层:0x7fa17a834ca0>>|||&lt_UI背景视图:0x7fa1785796e0;帧=(0;375 64);不透明=否;autoresize=W+H;userInteractionEnabled=NO;layer=&lt_UIBackdropViewLayer:0x7fa17863f2d0>>|||&lt_UI BackdropEffectView:0x7fa1786404e0;帧=(0;375 64);clipseToBounds=是;不透明=否;autoresize=W+H;userInteractionEnabled=NO;layer=<CABackdropLayer:0x7fa178640bc0>>|||<UI视图:0x7fa178641a30;帧=(0;375 64);hidden=YES;不透明=否;autoresize=W+H;userInteractionEnabled=NO;layer=<CA层:0x7fa178641b00>>|||<UIImageView:0x7fa17a83b0b0;帧=(0 64;375 0.5);userInteractionEnabled=NO;layer=<CA层:0x7fa17a825e20>>||<UI导航按钮:0x7fa17a832fd0;帧=(333 8;34 30);不透明=否;layer=<CA层:0x7fa17a8329d0>>|||<UI按钮标签:0x7fa17a835e10;帧=(0 4;34 20.5);text='项目';不透明=否;userInteractionEnabled=NO;layer=&lt_UILabelLayer:0x7fa17a8362c0>>||&lt_UI导航栏背景指示器视图:0x7fa178638f90;帧=(8 11.5;13 21);α=0;不透明=否;userInteractionEnabled=NO;layer=<CALayer:0x7fa1786392d0>>

此视图层次结构有时很难遵循,因此您可能需要:

  • WelcomeViewController的根view指定一个非零的tag(因为recursiveDescription将显示非零标记号)。这就是我上面所做的(我突出显示了这条线,这样你就可以快速看到它,lldb显然不会为你做这件事)。

  • 子类UIView,并将其指定为WelcomeViewController视图的基类(注意,这个UIView子类不必做任何事情,我们只需要一个不同的类,这样您就可以在recursiveDescription输出中区分它)。或者,

  • 从视图控制器层次结构中识别视图控制器的视图地址(在我的示例中为0x7fef02b6b520),并在视图层次结构中查找该视图。

这些技术中的任何一种都可以帮助您确定特定视图控制器的视图是否在层次结构中。

最新更新