2014-12-24 16 views
44

Sto mantenendo un vecchio progetto iOS basato su SDK 6.0.Come utilizzare UIAlertController per sostituire UIActionSheet?

un metodo su questo progetto chiamato

-(void) showComboBox:(UIView*)view:withOptions:(NSDictionary*)options

viene utilizzato per mostrare una casella combinata. Per raggiungere l'obiettivo, ha utilizzato UIActionSheet, che è deprecato su iOS8.

La mia soluzione è come questo:

 if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8) { 
     UIAlertController* alertController = [UIAlertController 
      alertControllerWithTitle:@"title" 
      message:@"message" 
      preferredStyle:UIAlertControllerStyleActionSheet]; 

     UIAlertAction* item = [UIAlertAction actionWithTitle:@"item" 
      style:UIAlertActionStyleDefault 
      handler:^(UIAlertAction *action) { 
      //do something here 
      //inform the selection to the WebView 
      ... 
      [alertController dismissViewControllerAnimated:YES completion:nil]; 
     }]; 

     UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 
      [alertController dismissViewControllerAnimated:YES completion:nil]; 
     }]; 

     [alertController addAction:item]; 
     [alertController addAction:cancelAction]; 
     //I am not sure whether it's the right way 
     if ([view.nextResponder isKindOfClass:UIViewController.class]) { 
      UIViewController* vc = (UIViewController*)view.nextResponder; 
      [vc presentViewController:alertController animated:YES completion:nil]; 
     } 

È che una soluzione adeguata?

Questo è quello che la maggior parte preoccupazione per: UIAlertController deve essere aggiunto ad un UIViewController ma posso solo ottenere il puntatore del UIView, così ho usato view.nextResponder per ottenere ciò che voglio, ma è che un buon modo?

risposta

63

Ho usato il seguente codice per mostrare il foglio di azione usando UIAlertViewController e funziona perfettamente.

- (IBAction)buttonClicked:(id)sender { 

    UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:@"Action Sheet" message:@"Using the alert controller" preferredStyle:UIAlertControllerStyleActionSheet]; 

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

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

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { 

     // Distructive button tapped. 
     [self dismissViewControllerAnimated:YES completion:^{ 
     }]; 
    }]]; 

    [actionSheet addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 

     // OK button tapped. 

     [self dismissViewControllerAnimated:YES completion:^{ 
     }]; 
    }]]; 

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

Edit:

È necessario per ottenere UIViewController oggetto qui. È possibile impostare una variabile globale o chiamare un metodo delegato oppure è possibile utilizzare la notifica per ottenere l'oggetto controller di visualizzazione in questo codice.

e l'ultima riga nel codice sopra sarà come.

[self.viewController presentViewController:actionSheet animated:YES completion:nil]; 

self.viewController è una variabile globale che sarà impostata prima che effettivamente ottenere questo punto di vista.

Perché l'approccio che stai seguendo ora utilizza view.nextResponder. Ho paura che non funzioni.

+0

quasi la stessa, tranne che per una piccola differenza: non riesco a ottenere il puntatore del UIViewController direttamente quindi devo UIView.nextResponder utente invece, e voglio sapere se è giusto. –

+0

Che cos'è 'view' nel codice? È una sottoview di qualsiasi controller di visualizzazione? – Kampai

+0

In realtà viene utilizzato da WebView per visualizzare una casella combinata, ad esempio PhoneGap. –

1

È possibile utilizzare invece view.window.rootViewController. Se non ti interessa il presentatore va bene.

25

Ho usato il foglio di azione per cambiare la foto del profilo. Ho seguito l'approccio Kampai, appena tolto dismissviewController chiamata perché mi stava prendendo a calci fuori di vista quando si preme Annulla o foto vista selezione

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

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

    // Cancel button tappped do nothing. 

}]]; 

[actionSheet addAction:[UIAlertAction actionWithTitle:@"Take photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 

    // take photo button tapped. 
    [self takePhoto]; 

}]]; 

[actionSheet addAction:[UIAlertAction actionWithTitle:@"Choose photo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 

    // choose photo button tapped. 
    [self choosePhoto]; 

}]]; 

[actionSheet addAction:[UIAlertAction actionWithTitle:@"Delete Photo" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { 

    // Distructive button tapped. 
    [self deletePhoto]; 

}]]; 
10

Swift aggiornamento -

let actionSheet = UIAlertController.init(title: "Please choose a source type", message: nil, preferredStyle: .actionSheet) 
    actionSheet.addAction(UIAlertAction.init(title: "Take Photo", style: UIAlertActionStyle.default, handler: { (action) in 
     self.openCamera() 
    })) 
    actionSheet.addAction(UIAlertAction.init(title: "Choose Photo", style: UIAlertActionStyle.default, handler: { (action) in 
     self.showPhotoLibrary() 
    })) 
    actionSheet.addAction(UIAlertAction.init(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { (action) in 
     // self.dismissViewControllerAnimated(true, completion: nil) is not needed, this is handled automatically, 
     //Plus whatever method you define here, gets called, 
     //If you tap outside the UIAlertController action buttons area, then also this handler gets called. 
    })) 
    //Present the controller 
    self.present(actionSheet, animated: true, completion: nil) 
0

Anche se può sembrare molto semplice, ci è un brutto problema con l'utilizzo di UIAlertController. È una perdita di memoria incline. Per verificare se hai il problema, basta inserire un breakpoint nel metodo "dealloc" del tuo controller di visualizzazione e verificare se è stato deallocato correttamente.

Stavo cercando una soluzione da un po 'di tempo ed ecco come uso il controller di allerta nella mia app.

+ (void)alertWithPresenting:(UIViewController *)presenting title:(NSString *)title 
         text:(NSString *)text buttons:(NSArray *)buttons 
        handler:(void (^)(UIAlertAction *action, NSUInteger index))handler 
{ 
     UIAlertController *alert = [UIAlertController 
            alertControllerWithTitle:title message:text 
            preferredStyle:UIAlertControllerStyleAlert]; 
     __weak __typeof(alert) weakAlert = alert; 
     for (NSString *title in buttons) { 
       UIAlertActionStyle style = UIAlertActionStyleDefault; 
       if ([title isEqualToString:[L10n cancelButton]]) 
         style = UIAlertActionStyleCancel; 
       else if ([title isEqualToString:[L10n deleteButton]]) 
         style = UIAlertActionStyleDestructive; 
       else if ([title isEqualToString:[L10n archiveButton]]) 
         style = UIAlertActionStyleDestructive; 

       UIAlertAction *action = [UIAlertAction actionWithTitle:title style:style handler:^(UIAlertAction *action) { 
         if (handler != nil) 
           handler(action, [buttons indexOfObject:action.title]); 
         [weakAlert dismissViewControllerAnimated:YES completion:nil]; 
       }]; 
       [alert addAction:action]; 
     } 
     [presenting presentViewController:alert animated:YES completion:nil]; 
} 

Questo non è tutto. Ecco un esempio di come lo si utilizza nel controller della vista. Nel mio caso la sua vista tabella con la ricerca, quindi il controller di presentazione potrebbe essere diverso.

- (void) deleteCases:(NSArray *)selectedRows 
{ 
     NSString *text = NSLocalizedStringWithDefaultValue(@"cases.delete.alert.text", 
                  @"Localizable", [NSBundle mainBundle], 
                  @"Deleted cases cannot be restored. Continue with delete?", 
                  @"Delete alert text"); 
     NSString *title = NSLocalizedStringWithDefaultValue(@"cases.delete.alert.title", 
                  @"Localizable", [NSBundle mainBundle], 
                  @"Delete cases", @"Detete alert title"); 
     UIViewController *presenting = self.searchController.active ? self.searchController : self; 
     __weak __typeof(presenting) weakPresenting = presenting; 
     __weak __typeof(self) weakSelf = self; 
     [YourClassName alertWithPresenting:weakPresenting title:title text:text 
            buttons:@[[L10n deleteButton], [L10n cancelButton]] 
            handler:^(UIAlertAction *action, NSUInteger index) 
     { 
       if (action.style == UIAlertActionStyleDestructive) { 
         __typeof(weakSelf) strongSelf = weakSelf; 
         // Perform your actions using @strongSelf 
       } 
     }]; 
} 
Problemi correlati