Swift Custom UIAlertView

Estoy intentando hacer una vista emergente de confirmación de eliminación. Debido a que el layout que deseo es muy diferente del estilo de la UIAlertView emergente típica de UIAlertView , decidí crear un ConfirmationViewController personalizado que desencadenaría en una window emergente.

UIAlertView es lo que parece ser el típico UIAlertView :

introduzca la descripción de la imagen aquí

Y aquí está lo que quiero que parezca mío:

introduzca la descripción de la imagen aquí

A continuación, le explico cómo realizo mi window emergente personalizada ConfirmationViewController :

 let confirmationViewController = ConfirmationViewController() confirmationViewController.delegate = self confirmationViewController.setTitleLabel("Are you sure you want to remove \(firstName)?") confirmationViewController.modalPresentationStyle = UIModalPresentationStyle.Popover confirmationViewController.prefernetworkingContentSize = CGSizeMake(230, 130) let popoverConfirmationViewController = confirmationViewController.popoverPresentationController popoverConfirmationViewController?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0) popoverConfirmationViewController?.delegate = self popoverConfirmationViewController?.sourceView = self.view popoverConfirmationViewController?.sourceRect = CGRectMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds),0,0) presentViewController( confirmationViewController, animated: true, completion: nil) 

Y así es como recibo la notificación cuando se presiona el button CANCEL o REMOVE :

 extension UserProfileTableViewController: ConfirmationViewControllerDelegate { func cancelButtonPressed() { print("Cancel button pressed") } func confirmationButtonPressed(objectToDelete: AnyObject?) { print("Delete button pressed") } } 

Sin embargo, lo que me gusta de usar un UIAlertView es que puedo codificar en la acción que quiero realizar cuando se presiona un button en particular, así:

 let alertController = UIAlertController(title: nil, message: nil, prefernetworkingStyle: .Alert) let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: {(ACTION) in print("Perform cancel action") }) let deleteAction = UIAlertAction(title: "Remove", style: .Destructive, handler: {(ACTION) in print("Perform delete action") }) alertController.addAction(cancelAction) alertController.addAction(deleteAction) presentViewController(alertController, animated: true, completion: nil) 

Entonces, mi pregunta es: ¿cómo puedo crear un manejador de finalización (en línea) de tal manera que cuando se presiona el button CANCEL o REMOVE con mi ConfirmationViewController personalizado puedo activar la acción, tal como lo he demostrado cómo se hace con el UIAlertController , en lugar de la forma actual, lo estoy haciendo con la delegación?

¿La respuesta es simplemente crear la window emergente personalizada que estoy buscando con un UIAlertController ? Y si es así, ¿cómo puedo personalizarlo al grado que estoy buscando?

Gracias de antemano y perdón por el largo post 🙂

PD Aquí se ConfirmationViewControllerDelegate aspecto de mi ConfirmationViewController y ConfirmationViewControllerDelegate :

 protocol ConfirmationViewControllerDelegate { func cancelButtonPressed() func confirmationButtonPressed(objectToDelete: AnyObject?) } class ConfirmationViewController: UIViewController { var didSetupConstraints = false let titleLabel = UILabel.newAutoLayoutView() let buttonContainer = UIView.newAutoLayoutView() let cancelButton = ButtonWithPressingEffect.newAutoLayoutView() let confirmationButton = ButtonWithPressingEffect.newAutoLayoutView() var delegate: ConfirmationViewControllerDelegate? var objectToDelete: AnyObject? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.whiteColor() titleLabel.numberOfLines = 0 cancelButton.backgroundColor = UIColor.colorFromCode(0x7f7f7f) cancelButton.layer.cornerRadius = 5 cancelButton.setAttributedTitle(NSMutableAttributedString( string: "CANCEL", attributes: [ NSFontAttributeName: UIFont(name: "AvenirNextLTPro-Demi", size: 12)!, NSForegroundColorAttributeName: UIColor.whiteColor(), NSKernAttributeName: 0.2 ] ), forState: UIControlState.Normal) cancelButton.addTarget(self, action: #selector(cancelButtonPressed), forControlEvents: .TouchUpInside) confirmationButton.backgroundColor = Application.networkingColor confirmationButton.layer.cornerRadius = 5 confirmationButton.setAttributedTitle(NSMutableAttributedString( string: "REMOVE", attributes: [ NSFontAttributeName: UIFont(name: "AvenirNextLTPro-Demi", size: 12)!, NSForegroundColorAttributeName: UIColor.whiteColor(), NSKernAttributeName: 0.2 ] ), forState: UIControlState.Normal) confirmationButton.addTarget(self, action: #selector(confirmationButtonPresssed), forControlEvents: .TouchUpInside) view.addSubview(titleLabel) view.addSubview(buttonContainer) buttonContainer.addSubview(cancelButton) buttonContainer.addSubview(confirmationButton) updateViewConstraints() } func cancelButtonPressed() { delegate?.cancelButtonPressed() dismissViewControllerAnimated(false, completion: nil) } func confirmationButtonPresssed() { delegate?.confirmationButtonPressed(objectToDelete) dismissViewControllerAnimated(false, completion: nil) } func setTitleLabel(text: String) { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = NSTextAlignment.Center paragraphStyle.lineSpacing = 4.5 titleLabel.attributedText = NSMutableAttributedString( string: text, attributes: [ NSFontAttributeName: UIFont(name: "AvenirNextLTPro-Regular", size: 14)!, NSForegroundColorAttributeName: UIColor.colorFromCode(0x151515), NSKernAttributeName: 0.5, NSParagraphStyleAttributeName: paragraphStyle ] ) } override func updateViewConstraints() { if !didSetupConstraints { titleLabel.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 10), excludingEdge: .Bottom) titleLabel.autoAlignAxisToSuperviewAxis(.Vertical) buttonContainer.autoPinEdge(.Top, toEdge: .Bottom, ofView: titleLabel, withOffset: 3) buttonContainer.autoAlignAxisToSuperviewAxis(.Vertical) buttonContainer.autoPinEdgeToSuperviewEdge(.Bottom, withInset: 10) let contactViews: NSArray = [cancelButton, confirmationButton] contactViews.autoDistributeViewsAlongAxis(.Horizontal, alignedTo: .Horizontal, withFixedSpacing: 7, insetSpacing: true, matchedSizes: false) cancelButton.autoPinEdgeToSuperviewEdge(.Top) cancelButton.autoPinEdgeToSuperviewEdge(.Bottom) cancelButton.autoSetDimensionsToSize(CGSize(width: 100, height: 50)) confirmationButton.autoPinEdgeToSuperviewEdge(.Top) confirmationButton.autoPinEdgeToSuperviewEdge(.Bottom) confirmationButton.autoSetDimensionsToSize(CGSize(width: 100, height: 50)) didSetupConstraints = true } super.updateViewConstraints() } } 

Algo como lo siguiente debería permitirlo. Tenga en count que hay algunas mejoras que podrían hacerse. Por ejemplo, podría usar un genérico para el object que se elimina en lugar de AnyObject. Tampoco es necesario que lo pases si pasas el cierre en línea de todas forms, por lo que probablemente podrías simplemente eliminarlo.

También puede hacer que sus botones sean más reutilizables en lugar de codificar para cancelar y eliminar, pero ahora nos estamos saliendo del tema 🙂

 class ConfirmViewController : UIViewController { var onCancel : (() -> Void)? var onConfirm : ((AnyObject?) -> Void)? var objectToDelete : AnyObject? func cancelButtonPressed() { // defenetworking to ensure it is performed no matter what code path is taken defer { dismissViewControllerAnimated(false, completion: nil) } let onCancel = self.onCancel // deliberately set to nil just in case there is a self reference self.onCancel = nil guard let block = onCancel else { return } block() } func confirmationButtonPresssed() { // defenetworking to ensure it is performed no matter what code path is taken defer { dismissViewControllerAnimated(false, completion: nil) } let onConfirm = self.onConfirm // deliberately set to nil just in case there is a self reference self.onConfirm = nil guard let block = onConfirm else { return } block(self.objectToDelete) } } let confirm = ConfirmViewController() confirm.objectToDelete = NSObject() confirm.onCancel = { // perform some action here } confirm.onConfirm = { objectToDelete in // delete your object here }