ios - ¿Cómo usar UIAlertController para reemplazar UIActionSheet?
objective-c (6)
He usado el siguiente código para mostrar la hoja de acción usando UIAlertViewController
y funciona perfecto.
- (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];
}
Editar:
Necesita obtener el objeto UIViewController
aquí. Puede establecer una variable global o llamar a un método delegado, o puede usar la notificación para obtener el objeto controlador de vista en este código.
y la última línea en el código anterior será similar.
[self.viewController presentViewController:actionSheet animated:YES completion:nil];
self.viewController
es una variable global que se establecerá antes de que realmente obtengas esta vista.
Porque el enfoque que estás siguiendo ahora usa view.nextResponder
. Me temo que puede no funcionar.
Estoy manteniendo un viejo proyecto de iOS basado en SDK 6.0.
Un método en este proyecto llamado
-(void) showComboBox:(UIView*)view:withOptions:(NSDictionary*)options
se usa para mostrar un cuadro combinado. Para lograr el objetivo, utilizó UIActionSheet, que está en desuso en iOS8.
Mi solución es así:
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];
}
¿Es esa una solución adecuada?
Esto es lo que más me preocupa : UIAlertController necesita ser agregado a un UIViewController pero solo puedo obtener el puntero de UIView, así que usé view.nextResponder para obtener lo que quiero, ¿pero es una buena manera?
He usado una hoja de acción para cambiar la imagen de perfil. Seguí el enfoque de Kampai, simplemente eliminé la llamada de destello del control ya que me estaba sacando de una vista al presionar Cancelar o seleccionar la vista de la foto
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];
}]];
Puede usar view.window.rootViewController
en view.window.rootViewController
lugar. Si no te importa el presentador, está bien.
Si bien puede parecer muy simple, hay un problema desagradable con el uso de UIAlertController
. Es una pérdida de memoria propensa. Para probar si tiene el problema, simplemente coloque un punto de interrupción en el método dealloc
su controlador de dealloc
y vea si está desasignado correctamente.
Estaba buscando una solución por bastante tiempo y así es como uso un controlador de alerta en mi aplicación.
+ (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];
}
Esto no es todo. Aquí hay un ejemplo de cómo lo usa en su controlador de vista. En mi caso, es una tableview
con búsqueda, por lo que la presentación del controlador puede ser diferente.
- (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
}
}];
}
Swift actualización -
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)
Swift 4
let alert = UIAlertController(title: "Select One", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil))
alert.addAction(UIAlertAction(title: "Export", style: UIAlertActionStyle.default, handler: { (action) in
// TODO: Export wordlist
}))
alert.addAction(UIAlertAction(title: "Import", style: UIAlertActionStyle.default, handler: { (action) in
// TODO: Import wordlist
}))
self.present(alert, animated: true, completion: nil)