未调用dismissViewController 完成处理程序

Posted

技术标签:

【中文标题】未调用dismissViewController 完成处理程序【英文标题】:dismissViewController completion handler not called 【发布时间】:2016-08-12 02:14:22 【问题描述】:

尝试使用链接中第一个答案中的代码(由 Kampai 提供): How to use UIAlertController to replace UIActionSheet?

但是,我的代码中甚至没有调用完成处理程序。

按下两个按钮后可以关闭警报操作表,但完成处理程序内部没有任何作用。 知道可能是什么问题吗?我是使用完成处理程序的新手,并试图在网上找到答案,但很少有人遇到与我相同的问题。

- (IBAction)takePhotoButtonPressed:(UIButton *)sender 
pressedButtonTagNumber = sender.tag;

UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];

[actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) 

    // Cancel button tappped
    [self dismissViewControllerAnimated:YES completion:^
    ];
]];

[actionSheet addAction:[UIAlertAction actionWithTitle:@"Take a Photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) 
    NSLog(@"!");
    // Take a Photo button tapped
    [self dismissViewControllerAnimated:YES completion:^
        NSLog(@"0"); // NOT CALLED
        // Initialize UIImagePickerController
        UIImagePickerController *takePhotoImagePickerController = [[UIImagePickerController alloc] init];            takePhotoImagePickerController.delegate = self;
        takePhotoImagePickerController.allowsEditing = YES;
        NSLog(@"1");
        // Check and assign image source
        if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 
            NSLog(@"2");
            UIAlertController *noCameraErrorSheet = [UIAlertController alertControllerWithTitle:@"Camera is not available" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
            [noCameraErrorSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) 
                // Cancel button tappped
                [self dismissViewControllerAnimated:YES completion:^
                ];
            ]];
         else 
            takePhotoImagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
            // Present UIImagePickerController
            [self presentViewController:takePhotoImagePickerController animated:YES completion:NULL];
        

    ];
]];

解决方案:

@Paulw11 解决方案效果很好:

1) UIAlertController 不需要dismissViewController。 2)如果一个新的 UIAlertController 包装它正在解散(显然),则无法调用它。 3) 最好提前检查和禁用按钮。

UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];

[actionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) 
]];

UIAlertAction *takePhotoActionButton = [UIAlertAction actionWithTitle:@"Take Photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) 
    [self takePhoto];
];
UIAlertAction *uploadPhotoActionButton = [UIAlertAction actionWithTitle:@"Upload from Library" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) 
    [self uploadPhoto];
];

// Disable take a photo button if source not available
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 
    [takePhotoActionButton setEnabled:FALSE];

// Disable upload a photo button if source not available
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) 
    [uploadPhotoActionButton setEnabled:FALSE];


[actionSheet addAction:takePhotoActionButton];
[actionSheet addAction:uploadPhotoActionButton];

// Present action sheet.
[self presentViewController:actionSheet animated:YES completion:nil];

【问题讨论】:

您是否正在调用dismissViewController:animated: 来关闭 UIAlertController?如果是这样,请不要这样做。点击按钮时它会自动关闭。在动作处理程序中,您只需要编写在选择动作按钮时要执行的任何代码。例如。您的“取消”操作将为空 谢谢!我也刚刚发现。只是想知道,我什么时候应该使用“[self dismissViewControllerAnimated:YES completion:^];”?为什么这个完成处理程序不起作用? 只要你想关闭一个视图控制器,你就可以使用它。您在这里不使用它的原因是UIAlertController 已经自行解散了。假设您想要一个超时,如果用户没有选择选项,则在 5 秒后取消警报;您可以启动一个计时器,然后在 5 秒后致电 dismissViewController:animated: 以删除警报。 @Paulw11 解释得很清楚。 【参考方案1】:

您无需在操作处理程序中调用 dismissViewController:animated: 即可删除警报。 UIAlertController 在调用动作处理程序代码之前调用它来关闭自身。

在您的操作处理程序中,您只需执行选择该操作时应该执行的任何操作:

在这种情况下:

在取消操作中,您无需执行任何操作 在您的“拍照”动作中,您会拍照

此外,从用户体验的角度来看,最好禁用“拍照”或在他们选择后立即显示警报,而不是在他们尝试拍照后发出警报;换句话说,早点而不是晚点指出问题

【讨论】:

另一个关于提醒用户的问题。现在我总是遇到异常“不允许在解除分配时尝试加载视图控制器的视图,并且可能导致未定义的行为 ()”。是因为我在当前的里面放了另一个 UIAlertController 吗?我有点困惑“谁”正在释放错误消息中提到的。网上搜索过,尝试从父控制器中移除 UIAlertController 等,现在没有任何效果。 是的,因为您将尝试在第一个上显示第二个警报控制器,但第一个正在被解雇。正如我所说,您应该在显示第一个警报之前检查相机是否可用。

以上是关于未调用dismissViewController 完成处理程序的主要内容,如果未能解决你的问题,请参考以下文章

Dismissviewcontroller 并执行 segue

糟糕编程的后果:dismissViewController 与 popViewController

将dismissViewController 与UIAlertController 一起使用

dismissViewController 或 popViewController 都不起作用

为 DismissViewController 添加通知而不进行子类化

DismissViewController UIButton 导致应用程序在 iPod touch 上崩溃