我曾经遇到这样一个情况:有一个子视图包含一个用于关闭它的按钮。当我弹出一个确认框来确认该操作时,它会发送一条消息给代理 - 即包含该子视图的视图控制器 - 以便移除该子视图。
最初,我从一个UIView中弹出了一个UIAlertView。为了使用UIAlertController进行重构,因为UIAlertController无法像UIAlertView那样自己呈现,我想出了以下解决方案(在Swift中,很容易转换成ObjC):
向子视图添加一个协议:
protocol MySubviewDelegate {
func displayAlert(alert : UIAlertController)
func shouldRemoveSubview(sender : AnyObject)
}
为子视图添加代理,并添加按钮/手势点击的处理程序:
class MySubview : UIView {
var subviewDelegate : MySubviewDelegate!
...
func handleTap(sender : AnyObject) {
var alert = UIAlertController(title: "Confirm Delete",
message: "This action is permanent. Do you wish to continue?",
preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Cancel",
style: UIAlertActionStyle.Cancel,
handler: nil))
alert.addAction(UIAlertAction(title: "Confirm",
style: UIAlertActionStyle.Default,
handler: { (action : UIAlertAction!) -> Void in
self.subviewDelegate.shouldRemoveSubview(self)
}))
self.subviewDelegate.displayAlert(alert)
}
}
在调用的UIViewController中将其设置为子视图的代理,例如在其viewDidLoad()方法中,并包含协议方法:
class viewController : UIViewController, MySubviewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.subviewDelegate = self
...
}
func displayAlert(alert : UIAlertController) {
presentViewController(alert, animated: true, completion: nil)
}
func shouldRemoveSubview(sender : AnyObject) {
var subview = sender as MySubview
subview.removeFromSuperview()
...
}
...
}
这样可以避免查找最上层的视图控制器,或向子视图传递视图控制器的引用(除了在对象/委托关系中)。