У меня есть NSOutlineView
с базовой моделью, состоящей из узлов. Эти узлы имеют множество различных возможностей, созданных с помощью протоколов.
РЕДАКТИРОВАТЬ - чтобы уточнить, возможности, описанные каждым протоколом, реализованы как расширения протокола по умолчанию в расширениях, поэтому в настоящее время подклассы не должны содержать какие-либо методы для соответствия протоколу.
У меня есть NSMenu
, который содержит действия, которые могут быть выполнены на Node
s в представлении.
Я хотел бы проверить пункты меню для текущего выбранного Node
, но я не могу придумать, как это сделать, не написав одну массивную функцию для базового класса.
Проверки, которые мне нужны, - это не просто соответствие протокола - например, Node
, который реализует протокол Indentable, не может иметь отступ при любых обстоятельствах. Мне нужен canIndent()
, чтобы дополнить метод indent()
.
Давным-давно в C ++ я реализовал нечто подобное, построив таблицу проверки в виде статического массива для базового класса. Подклассы регистрируют свои методы при запуске. Однако при использовании Swift я не могу поместить выражения на верхний уровень, чтобы сделать это чисто, и нет кода инициализации на уровне протокола.
Единственный способ, которым я могу думать сейчас, - это использовать метод на Узле в такой форме:
func validAction(_ action: Selector) -> Bool
{
switch(action)
{
case #selector(indent):
if self is Indentable {
return (self as! Indentable).canIndent
...
РЕДАКТИРОВАТЬ - Как отметил Виллек, я мог написать это на каждом подклассе, который соответствует протоколу, но это потребовало бы много повторений.
В идеале я бы построил метод на узле вида:
func validAction(_ action: Selector) -> Bool
{
if self.responds(to: action) {
return validations[action].valid
}
return false
}
Кто-нибудь делал это хорошо!?
РЕДАКТИРОВАТЬ - Одна из идей может заключаться в том, чтобы что-то сделать с описанием селектора для создания селектора проверки с соглашением об именах - например, indent()
-> indentValid()