Swift 自定义 UIAlertView
Swift Custom UIAlertView
我正在尝试制作确认删除弹出视图。因为我想要的设计与典型的 UIAlertView
弹出窗口的样式非常不同,所以我决定创建一个自定义的 ConfirmationViewController
来触发弹出窗口。
这是典型的 UIAlertView
的样子:
这就是我希望我的样子:
这是我目前制作自定义 ConfirmationViewController
弹出窗口的方式:
let confirmationViewController = ConfirmationViewController()
confirmationViewController.delegate = self
confirmationViewController.setTitleLabel("Are you sure you want to remove \(firstName)?")
confirmationViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
confirmationViewController.preferredContentSize = 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)
下面是按下 CANCEL
或 REMOVE
按钮时我收到通知的方式:
extension UserProfileTableViewController: ConfirmationViewControllerDelegate {
func cancelButtonPressed() {
print("Cancel button pressed")
}
func confirmationButtonPressed(objectToDelete: AnyObject?) {
print("Delete button pressed")
}
}
但是,我喜欢使用 UIAlertView
的一点是,我可以在按下特定按钮时对要执行的操作进行硬编码,如下所示:
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .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)
所以我的问题是,如何创建一个完成处理程序(内联),以便在使用我的自定义 ConfirmationViewController
按下 CANCEL
或 REMOVE
按钮时可以触发动作,就像我已经展示了它是如何用 UIAlertController
完成的,而不是我用委托做的当前方式?
是否只需创建我正在寻找的带有 UIAlertController
的自定义弹出窗口?如果是这样,我如何才能将其自定义到我正在寻找的程度?
提前致谢,抱歉拖了这么久 post :)
P.S。这是我的 ConfirmationViewController
和 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.redColor
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()
}
}
像下面这样的东西应该允许它。请注意,可以进行很多改进。例如,您可以对要删除的对象使用泛型,而不是 AnyObject。如果你通过内联闭包,你也不一定需要传递它,所以你可能只是删除它。
您还可以让您的按钮更具可重用性,而不是通过硬编码来取消和删除,但现在我们离题了:)
class ConfirmViewController : UIViewController {
var onCancel : (() -> Void)?
var onConfirm : ((AnyObject?) -> Void)?
var objectToDelete : AnyObject?
func cancelButtonPressed() {
// defered 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() {
// defered 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
}
我正在尝试制作确认删除弹出视图。因为我想要的设计与典型的 UIAlertView
弹出窗口的样式非常不同,所以我决定创建一个自定义的 ConfirmationViewController
来触发弹出窗口。
这是典型的 UIAlertView
的样子:
这就是我希望我的样子:
这是我目前制作自定义 ConfirmationViewController
弹出窗口的方式:
let confirmationViewController = ConfirmationViewController()
confirmationViewController.delegate = self
confirmationViewController.setTitleLabel("Are you sure you want to remove \(firstName)?")
confirmationViewController.modalPresentationStyle = UIModalPresentationStyle.Popover
confirmationViewController.preferredContentSize = 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)
下面是按下 CANCEL
或 REMOVE
按钮时我收到通知的方式:
extension UserProfileTableViewController: ConfirmationViewControllerDelegate {
func cancelButtonPressed() {
print("Cancel button pressed")
}
func confirmationButtonPressed(objectToDelete: AnyObject?) {
print("Delete button pressed")
}
}
但是,我喜欢使用 UIAlertView
的一点是,我可以在按下特定按钮时对要执行的操作进行硬编码,如下所示:
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .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)
所以我的问题是,如何创建一个完成处理程序(内联),以便在使用我的自定义 ConfirmationViewController
按下 CANCEL
或 REMOVE
按钮时可以触发动作,就像我已经展示了它是如何用 UIAlertController
完成的,而不是我用委托做的当前方式?
是否只需创建我正在寻找的带有 UIAlertController
的自定义弹出窗口?如果是这样,我如何才能将其自定义到我正在寻找的程度?
提前致谢,抱歉拖了这么久 post :)
P.S。这是我的 ConfirmationViewController
和 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.redColor
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()
}
}
像下面这样的东西应该允许它。请注意,可以进行很多改进。例如,您可以对要删除的对象使用泛型,而不是 AnyObject。如果你通过内联闭包,你也不一定需要传递它,所以你可能只是删除它。
您还可以让您的按钮更具可重用性,而不是通过硬编码来取消和删除,但现在我们离题了:)
class ConfirmViewController : UIViewController {
var onCancel : (() -> Void)?
var onConfirm : ((AnyObject?) -> Void)?
var objectToDelete : AnyObject?
func cancelButtonPressed() {
// defered 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() {
// defered 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
}