最近在看POP(Protocol-Oriental Programming)方向的文章, 碰巧有个需求适合用POP解决, 记录一下.
需求是这样的:
当前控制器, 就叫CurrentViewController吧, 需要Push到一个另外的控制器选择一个Staff对象, 就叫StaffViewController吧, StaffViewController里会根据Staff所在的部门, 层级不同, 选择的时候会push到不同的下一级控制器, 这些下一级控制器里装着不同的Staff或者其他部门, 选择其他部门又会不一样的操作, 我需要这些不同的控制器在完成选择Staff对象的时候都直接pop回CurrentViewController里.
我的协议是这样设计的:
protocol StaffSelectable {
}
extension StaffSelectable where Self: MyBaseViewController {
func actionAfterSelectStaff(staff: ContactStaff, ifNotForSelectStaff: @escaping () -> Void) {
if isDuringStaffSelection {
// 进行选择后的操作
// 跳转回CurrentViewController
self.popToCurrentViewController()
} else {
ifNotForSelectStaff()
}
}
private func popToCurrentViewController() {
for vc in self.navigationController?.viewControllers ?? [] {
if vc.isKind(of: CurrentViewController.self) {
self.navigationController?.popToViewController(vc, animated: true)
}
}
}
}
在遵守这个协议的控制器种调用的代码:
class SomeBaseViewController: MyBaseViewController, StaffSelectable {
private func didSelectStaff(vc: UIViewController, staff: Staff) {
self.actionAfterSelectStaff(staff: staff) {
// 提供这个控制器在不是选Staff的用途时的功能
self.navigationController?.pushViewController(someOtherViewController, animated: true)
}
}
}
这样遵守这个协议的控制器在选完Staff的时候统一调这个方法就可以, 不用在基类定义方法, 更不用满篇去CV代码了✌️