ios - example - uialertcontroller objective c
¿Cuál es la mejor manera de verificar si un UIAlertController ya se está presentando? (13)
Tengo una vista de tabla que, cuando se carga, cada celda podría devolver un NSError, que he elegido mostrar en un UIAlertController. El problema es que recibo este error en la consola si se devuelven varios errores.
Advertencia: Intente presentar UIAlertController: 0x14e64cb00 en MessagesMasterVC: 0x14e53d800 que ya está presentando (nulo)
Idealmente, me gustaría manejar esto en mi método de extensión UIAlertController.
class func simpleAlertWithMessage(message: String!) -> UIAlertController {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
alertController.addAction(cancel)
return alertController
}
Basado en la respuesta de matt, cambié la extensión a una extensión UIViewController, es mucho más limpia y ahorra mucho código presentViewController.
func showSimpleAlertWithMessage(message: String!) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
alertController.addAction(cancel)
if self.presentedViewController == nil {
self.presentViewController(alertController, animated: true, completion: nil)
}
}
Respuesta rápida de 4.2+
if UIApplication.topViewController()!.isKind(of: UIAlertController.self) {
print("UIAlertController is presented")}
Para aquellos que no saben cómo obtener la mayor cantidad de Viewcontroller
extension UIApplication {
public class func topViewController(_ base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(nav.visibleViewController)
}
if let tab = base as? UITabBarController {
if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(presented)
}
return base
}}
Aquí hay una solución que uso en Swift 3. Es una función que muestra una alerta al usuario, y si la llama varias veces antes de que el usuario la haya descartado, agregará el nuevo texto de alerta a la alerta que ya se está presentando. . Si se presenta alguna otra vista, la alerta no aparecerá. No todos estarán de acuerdo con ese comportamiento, pero funciona bien para situaciones simples.
extension UIViewController {
func showAlert(_ msg: String, title: String = "") {
if let currentAlert = self.presentedViewController as? UIAlertController {
currentAlert.message = (currentAlert.message ?? "") + "/n/nUpdate:/(title): /(msg)"
return
}
// create the alert
let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
// show the alert
self.present(alert, animated: true, completion: nil)
}
}
Bueno, las soluciones sugeridas anteriormente tienen un problema esencial desde mi punto de vista:
Si le pregunta a su ViewController, si el atributo ''presentadaViewController'' es nulo y la respuesta es falsa, no puede llegar a la conclusión de que su UIAlertController ya está presentado. Podría ser cualquier ViewController presentado, por ejemplo, una ventana emergente. Por lo tanto, mi sugerencia para verificar con seguridad si la alerta ya está en la pantalla es la siguiente (emita el PresentViewController como UIAlertController):
if self.presentedViewController == nil {
// do your presentation of the UIAlertController
// ...
} else {
// either the Alert is already presented, or any other view controller
// is active (e.g. a PopOver)
// ...
let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?
if thePresentedVC != nil {
if let thePresentedVCAsAlertController : UIAlertController = thePresentedVC as? UIAlertController {
// nothing to do , AlertController already active
// ...
print("Alert not necessary, already on the screen !")
} else {
// there is another ViewController presented
// but it is not an UIAlertController, so do
// your UIAlertController-Presentation with
// this (presented) ViewController
// ...
thePresentedVC!.presentViewController(...)
print("Alert comes up via another presented VC, e.g. a PopOver")
}
}
}
Descarte el controlador actual y presente el controlador de alerta como
func alert(_ message:String) {
let alert = UIAlertController(title: "Error!", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
self.dismiss(animated: false, completion: nil)
self.present(alert, animated: true,completion: nil)
}
Esta categoría puede gestionar automáticamente todos los controladores modales incluidos de UIAlertController.
Esto me sucedió cuando traté de manejar los
UI elements
en un hilo diferente al hilo
Main Thread
.
Tuve el mismo problema cuando mostré la alerta en un bloque de matriz de filtros.
Cuando saqué el presentador de alerta del bloque de filtro, desapareció la advertencia de la consola.
Lo usé para detectar y eliminar y alertar.
Primero creamos una alerta con la siguiente función.
var yourAlert :UIAlertController!
func useYouAlert (header: String, info:String){
yourAlert = UIAlertController(title:header as String, message: info as String, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: self.langText[62]as String, style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print("OK")
}
yourAlert.addAction(okAction)
self.present(yourAlert.addAction, animated: true, completion: nil)
}
Y en alguna otra parte de tu código
if yourAlert != nil {
yourAlert.dismiss(animated: true, completion: nil)
}
No es el UIAlertController el que "ya está presentando", es MessagesMasterVC. Un controlador de vista solo puede presentar otro controlador de vista a la vez. De ahí el mensaje de error.
En otras palabras, si le ha dicho a un controlador de vista que presente
presentViewController:...
, no puede volver a hacerlo hasta que se haya descartado el controlador de vista presentado.
Puede preguntarle a MessagesMasterVC si ya está presentando un controlador de vista examinando su ControladorViewView
presentedViewController
.
Si no es
nil
, no le diga a
presentViewController:...
- ya está presentando un controlador de vista.
Para el último lenguaje Swift puede usar lo siguiente:
var alert = presentedViewController
if alert != nil && (alert is UIAlertController) {
// YES UIAlertController is already presented*
} else {
// UIAlertController is not presented OR visible.
}
Simplemente descarte el controlador actual y presente el que desee, es decir
self.dismiss(animated: false, completion: nil)
self.displayAlertController()
Simplemente podemos verificar si se presenta algún controlador de vista.
si se presenta, compruebe si es una especie de UIAlertController.
id alert = self.presentedViewController;
if (alert && [alert isKindOfClass:[UIAlertController class]])
{
*// YES UIAlertController is already presented*
}
else
{
// UIAlertController is not presented OR visible.
}
puede probar, en una sola línea, si ya se presentó una alerta:
if self.presentedViewController as? UIAlertController != nil {
print ("alert already presented")
}
if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) {
// UIAlertController is presenting.Here
}