2014-09-17 4 views
4

Я столкнулся с каким-то странным поведением iOS8, и я не знаю, как с ним справиться. Кажется, это ошибка. Возможно, у вас есть хорошая идея для обходного пути.UIActionSheet несколько вариантов выбора iOS8 - не удаляет UIWindow

Способ воспроизведения: создайте таблицу UIActionSheet с как минимум двумя параметрами. В iOS8 у вас есть возможность выбрать сразу несколько вариантов. Просто коснитесь em: работает как на устройстве, так и на симуляторе. Это может случиться и с плохой целью.

Метод Делегат

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

будет называться дважды. Если это остановится здесь, это будет легко: просто проигнорируйте второй вызов делегата. Проблема заключается в том, что _UIAlertControllerShimPresenterWindow никогда не отклоняется, что приводит к блокировке пользовательского интерфейса, так как окна нашего 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 

никогда не вызывается.

переустановку UIWindow в UIApplication с грязным хаком как:

[[(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 
+0

Я тоже вижу ту же проблему. Вот радар: http://www.openradar.me/radar?id=4786870772826112 –

ответ

0

Сценарий вы описали не представляется возможным произойти , с таким уровнем выпуска от Apple. Возможно, возникла проблема с назначением делегата или чем-то вроде этого. Но, вы можете использовать этот метод, чтобы отклонить ActionSheet в вас метод делегата (это только работа вокруг):

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

Как это:

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

Я просто попробовал ваше решение, и оно не работает. Сожалею. Мне кажется, что вы сами не пробовали ... «Сценарий, который вы описали, не может произойти, с таким уровнем выпуска от Apple». В моей защите я был в шоке от такой ошибки. Но он там. Попробуйте ... С уважением, толстый – fat

+0

Как я уже говорил, вам не нужен этот код .. его работа вокруг.Вы должны проверить назначение делегата и ваш поток. Я не могу ожидать, что Apple даст эту ошибку. Но если вы все еще говорите об этом от яблока, вы должны сообщить об этом Apple. Другое предложение - вы должны попробовать свой код в другом проекте, а затем посмотреть, что там происходит. –

+0

Поскольку вы мне не верите, я добавил пример ViewController. Попробуй! – fat

1

Я считаю, что лучший способ решить эту проблему заключается в использовании UIAlertController в iOS 8 вместо 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 
} 
+0

Я могу подтвердить, что проблема не для меня, используя UIAlertController. –

+0

Себастьян, вы используете iOS 8.3+? Я нашел, что использование UIAlertController все еще содержит ошибку, в которой вы можете многократно использовать несколько вариантов. – micnguyen