UIActionSheet多选可能iOS8 - 不删除UIWindow

时间:2014-09-17 13:51:52

标签: uikit ios8 uiactionsheet uiwindow

我遇到了一些奇怪的iOS8行为,我不知道如何处理它。对我来说似乎是一个错误。也许你对解决方法有个好主意。

重现方法:创建一个至少有两个选项的UIActionSheet。在iOS8中,您可以一次选择多个选项。只需触摸em:在设备和模拟器上工作。这可能也会在糟糕的瞄准时发生。

委托方法

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;

将被调用两次。如果它会停在这里这很容易:只需忽略第二个委托调用。问题是_UIAlertControllerShimPresenterWindow永远不会被解雇,这会导致UI阻塞,因为我们的UIApplication的窗口没有收到任何触摸事件。如果你运行

po [[[UIApplication sharedApplication] keyWindow] recursiveDescription]

在调试模式下,您将获得以下输出:

<_UIAlertControllerShimPresenterWindow: 0x7bf5a3d0; frame = (0 0; 320 568); opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x7bf5af80>; layer = <UIWindowLayer: 0x7bf5a620>>
    | <UIView: 0x7bf5c460; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x7bf5c3f0>>

也是委托方法

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
永远不会打电话给

将UIApplication的UIWindow重新设置为脏兮兮的黑客,如:

[[(MyApplicationDelegate *) [UIApplication sharedApplication].delegate window] makeKeyAndVisible];

不起作用。您对如何解决这个问题有任何其他想法吗?

要重现,只需将以下ViewController放入UINavigationController,就会出现问题......万一你不相信我:

#import "ViewController.h"

@interface ViewController () <UIActionSheetDelegate>

@end

@implementation ViewController

- (void)loadView
{
    self.view = [[UIView alloc] initWithFrame: CGRectZero];
    self.view.backgroundColor = [UIColor whiteColor];

    UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithTitle:@"ActionSheet" style:UIBarButtonItemStylePlain target:self action:@selector(buttonTouchUpInside:)];

    self.toolbarItems = @[buttonItem];
    [self.navigationController setToolbarHidden: NO];
}

- (void)viewDidLoad 
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

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

#pragma mark Target Action

- (IBAction)buttonTouchUpInside:(id)sender
{
    UIActionSheet *aSheet = [[UIActionSheet alloc] initWithTitle:@"Choose an option" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:@"Option 1", @"Option 2", @"Option 3", @"Option 4", nil];

    [aSheet showFromToolbar: self.navigationController.toolbar];
//    [aSheet showInView: self.view]; // doesn't make any difference
}

#pragma mark UIActionSheetDelegate

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    NSLog(@"Clicked at button index %lu", (unsigned long) buttonIndex);
}

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    NSLog(@"Did dismiss with button index %lu", (unsigned long) buttonIndex);
}

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    NSLog(@"Will dismiss with button index %lu", (unsigned long) buttonIndex);
}

@end

3 个答案:

答案 0 :(得分:1)

我认为解决此问题的最佳方法是在iOS 8中使用UIAlertController而不是UIActionSheet

以下是如何以适用于iOS 8或iOS 7的方式实现它的示例:

- (IBAction)buttonCallingActionSheetPressed:(UIBarButtonItem *)sender
{
    id alertControllerClass = NSClassFromString(@"UIAlertController");

    if (alertControllerClass)
    {
        UIAlertAction *sheetAction = nil;
        UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:nil
                                                                                       message:nil
                                                                                preferredStyle:UIAlertControllerStyleActionSheet];

        sheetAction = [UIAlertAction actionWithTitle:@"Do something"
                                          style:UIAlertActionStyleDefault
                                        handler:^(UIAlertAction *action) {
                                            [self actionSheetSelectedIndex:0];
                                        }];
        [actionSheetController addAction:sheetAction];

        sheetAction = [UIAlertAction actionWithTitle:@"Cancel"
                                          style:UIAlertActionStyleCancel
                                        handler:^(UIAlertAction *action) {
                                            [self actionSheetSelectedIndex:1];
                                        }];
        [actionSheetController addAction:sheetAction];

        [self presentViewController:actionSheetController animated:YES completion:nil];
    }
    else
    {
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                                 delegate:self
                                                        cancelButtonTitle:@"Cancel"
                                                   destructiveButtonTitle:nil
                                                        otherButtonTitles:@"Do something", nil];
        [actionSheet showFromToolbar:self.navigationController.toolbar];
    }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    [self actionSheetSelectedIndex:buttonIndex];
}

- (void)actionSheetSelectedIndex:(NSInteger)selectedAction
{
    // Your logic goes here
}

答案 1 :(得分:0)

您所描述的场景不可能发生,具有Apple发布的此级别。委托分配或类似的东西可能存在一些问题。但是,您可以使用此方法来解除委托方法中的ActionSheet(这只是一种解决方法):

- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated;

像这样:

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
     [actionSheet dismissWithClickedButtonIndex:actionSheet.cancelButtonIndex animated:YES];
}

答案 2 :(得分:0)

此问题已在iOS 8.3 +。

中修复