Ответ 1
Кажется, что у вас есть конфигурация бара по умолчанию, но специфические (для подкласса UIViewController) реализаций действий кнопки бара. Вы упомянули 1. "Расширение должно знать, как создать экземпляр нового контроллера представления" и второй пункт 2. "Предполагается, что вы хотите только представить UIViewController", это хороший признак того, что ваше расширение должно делегировать это задание подклассу который знает, что делать с этими действиями. Здесь я сделал пример реализации:
enum BarButtonItemPosition {
case right, left
}
enum BarButtonItemType {
case menu(BarButtonItemPosition)
case close(BarButtonItemPosition)
case notification(BarButtonItemPosition)
}
/// Has default implementation on UIViewControllers that conform to BarButtonActions.
protocol BarButtonItemConfiguration: class {
func addBarButtonItem(ofType type: BarButtonItemType)
}
/// Hate that we're forced to expose button targets to objc runtime :(
/// but I don't know any other way for the time being, maybe in Swift 6 :)
@objc protocol BarButtonActions {
@objc func presentLeftMenu(_ sender:AnyObject)
@objc func dismissController(_ sender:AnyObject)
@objc func showNotification(_ sender:AnyObject)
}
extension BarButtonItemConfiguration where Self: UIViewController, Self: BarButtonActions {
func addBarButtonItem(ofType type: BarButtonItemType) {
func newButton(imageName: String, position: BarButtonItemPosition, action: Selector?) {
let button = UIBarButtonItem(image: UIImage(named: imageName), style: .plain, target: self, action: action)
switch position {
case .left: self.navigationItem.leftBarButtonItem = button
case .right: self.navigationItem.rightBarButtonItem = button
}
}
switch type {
case .menu(let p): newButton(imageName: "", position: p, action: #selector(Self.presentLeftMenu(_:)))
case .notification(let p): newButton(imageName: "", position: p, action: #selector(Self.showNotification(_:)))
case .close(let p): newButton(imageName: "", position: p, action: #selector(Self.dismissController(_:)))
}
}
}
/// Conform to this in subclasses of UIViewController and implement BarButtonActions (its impl. differs from vc to vc).
protocol BarButtonConfigarable: BarButtonItemConfiguration, BarButtonActions {}
/// example
class SampleVC: UIViewController, BarButtonConfigarable {
override func viewDidLoad() {
super.viewDidLoad()
addBarButtonItem(ofType: .menu(.right))
addBarButtonItem(ofType: .menu(.left))
}
@objc func presentLeftMenu(_ sender:AnyObject) {
// TODO:
}
@objc func dismissController(_ sender:AnyObject) {
// TODO:
}
@objc func showNotification(_ sender:AnyObject) {
// TODO:
}
}