AlertViewController - 其视图不在 window 层次结构问题中

AlertViewController - whose view is not in the window hierarchy Issue

在下面的代码中,我尝试仅在特定事件发生时调用 handleEvent 方法。为此,我 post 通知事件发生的地方(未在下面的代码中显示),以便观察者和 handleEvent 观察通知(如下面的代码所示)。

我想要弹出警报 viewController 并获取文本条目,以便我可以接收它。 但我收到以下错误:

Warning: Attempt to present <UIAlertController: 0x7f9d1347ed90> on <MSMDemoFirstViewController: 0x7f9d1347e920> whose view is not in the window hierarchy!

我无法理解,虽然我使用的是单例,但我无法正确获取 alertViewController。任何帮助都会有很大用处。

   #import "MSMDemoFirstViewController.h"
#import "CAMDOReporter.h"
static MSMDemoFirstViewController * instance = nil;
@interface MSMDemoFirstViewController ()

@end

@implementation MSMDemoFirstViewController

+ (MSMDemoFirstViewController *)sharedInstance {
    // Singleton implementation
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (instance == nil) {
            instance = [[MSMDemoFirstViewController alloc] init];
        }
    });
    return instance;
}

+(void)load{
[[NSNotificationCenter defaultCenter] addObserver:[MSMDemoFirstViewController sharedInstance] selector:@selector(handleEvent:) name:EVENT_OCCURRED object:nil];
}


+(void) initialize{

}
- (void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    //[[CAMDOReporter sharedInstance] startApplicationTransaction:@"DemoEventApplicationTransaction"];
   // [self showAlert];
}

-(void)showAlert{
    NSLog(@"2ew");
    NSString *title = NSLocalizedString(@"A Short Title Is Best", nil);
    NSString *message = NSLocalizedString(@"A message should be a short, complete sentence.", nil);
    NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil);
    NSString *otherButtonTitle = NSLocalizedString(@"OK", nil);

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];

    [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
        // If you need to customize the text field, you can do so here.
    }];

    // Create the action.
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"The simple alert's cancel action occured.");
    }];

    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSLog(@"The \"Text Entry\" alert's other action occured.");
    }];
    // Add the action.
    [alertController addAction:cancelAction];
    [alertController addAction:otherAction];
    [self presentViewController:alertController animated:YES completion:nil];
}

-(void)handleEvent:(NSNotification *)note{
    NSLog(@"Handle Crash Event");
    NSDictionary *crashData  = [note userInfo];
    if(crashData !=nil){
        //Implement any UI Logic to get any response from the user. e.g. AlertView, TextFields.
        //Once the feedback is received convert it into NSString and send the data.
        // Show a text entry alert with two custom buttons.
        [[MSMDemoFirstViewController sharedInstance] showAlert];
        NSString *feedback=[[NSUserDefaults standardUserDefaults] objectForKey:@"crashDetails"];
        [[CAMDOReporter sharedInstance] setCustomerFeedback:feedback];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

现在我得到的输出是:

2015-01-21 20:17:45.762 CAMAADemo[18891:1558312] Handle Crash Event
2015-01-21 20:17:45:762 CAMAADemo[18891:1807] Posting Notification about crash
2015-01-21 20:17:45.762 CAMAADemo[18891:1558312] 2ew
2015-01-21 20:17:45.778 CAMAADemo[18891:1558312] Warning: Attempt to present <UIAlertController: 0x7ff5d2273580> on <MSMDemoFirstViewController: 0x7ff5d2204be0> whose view is not in the window hierarchy!

这意味着调用将调用 showAlert 方法,但随后我遇到了同样的错误。

即使是下面的代码也无济于事。

-(void)viewDidLoad{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCrashEvent:) name:CAMAA_CRASH_OCCURRED object:nil];
}
-(void)showAlert{
    NSLog(@"2ew");
    NSString *title = NSLocalizedString(@"A Short Title Is Best", nil);
    NSString *message = NSLocalizedString(@"A message should be a short, complete sentence.", nil);
    NSString *cancelButtonTitle = NSLocalizedString(@"Cancel", nil);
    NSString *otherButtonTitle = NSLocalizedString(@"OK", nil);

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];

    [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
        // If you need to customize the text field, you can do so here.
    }];

    // Create the action.
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"The simple alert's cancel action occured.");
    }];

    UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        NSLog(@"The \"Text Entry\" alert's other action occured.");
    }];
    // Add the action.
    [alertController addAction:cancelAction];
    [alertController addAction:otherAction];
    [self presentViewController:alertController animated:YES completion:nil];
}

-(void)handleCrashEvent:(NSNotification *)note{
    NSLog(@"Handle Crash Event");
    NSDictionary *crashData  = [note userInfo];
    if(crashData !=nil){
        //Implement any UI Logic to get any response from the user. e.g. AlertView, TextFields.
        //Once the feedback is received convert it into NSString and send the data.
        // Show a text entry alert with two custom buttons.
        [self showAlert];
        NSString *feedback=[[NSUserDefaults standardUserDefaults] objectForKey:@"crashDetails"];
        [[CAMDOReporter sharedInstance] setCustomerFeedback:feedback];
    }
}

您的代码的问题是您创建了一个全新的视图控制器并显示了来自新控制器的警报。但该控制器尚未显示,因此出现错误消息。

修复此代码的正确方法是显示来自实际呈现的视图控制器的警报。

为此,将实际的视图控制器实例注册为通知处理程序,而不是在 load 方法中注册 class。

进行以下更改:

  1. 消除 load 方法。
  2. 将对 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEvent:) name:EVENT_OCCURRED object:nil]; 的调用移至 viewDidLoad 方法。
  3. handleEvent:更改为实例方法。
  4. [[[self alloc]init] showAlert]; 更改为 [self showAlert];
  5. 添加一个dealloc方法并注销通知观察者。