iOS: обработка UIGestureRecognisers в UI(Sub)Views

Я хотел бы знать, как наилучшим образом решить следующую проблему:

У меня есть один ViewController. Его представление содержит большое количество сложных подпредставлений (подкласс UIView). Из-за сложности некоторые из этих UIViews инициализируют свои собственные UIGestureRecognisers и реализуют соответствующие целевые действия. Поскольку я хочу координировать жесты различных подпредставлений, я должен установить один раз ViewController в качестве делегата жеста. Для этого есть разные возможности.

1) Инициализируйте ВСЕ жесты в viewController (это приведет к массивному viewController)

2) определение протокола в UIVIews (getViewController), реализованного ViewController

@protocol CustomViewDelegate <NSObject>
@required
- (UIViewController *)getViewController;
@end

3) настроить метод инициализации UIViews и использовать ViewController в качестве опции.

- (id)initWithFrame:(CGRect)frame andViewController:(UIViewController *)vc;

Какова самая элегантная возможность решить эту проблему? Можно ли реализовать целевые действия внутри объекта UIView?

Спасибо за ваши мысли...


person kiessan    schedule 14.07.2011    source источник


Ответы (1)


Если вы определяете пользовательские подклассы UIView, вы можете вложить в них столько логики, сколько имеет смысл хранить локально по отношению к ним, дать им делегированные протоколы для передачи чего-либо еще, и, пока вы предоставляете делегат как IBOutlet, вы может подключить ваш контроллер представления в качестве соответствующего делегата непосредственно в интерфейсном конструкторе или в части дизайнера пользовательского интерфейса Xcode 4. Я лично думаю, что это был бы наиболее естественный путь вперед, поскольку он объединяет любую логику, специфичную для представления, непосредственно в представлении и позволяет вам прокладывайте проводку там, где вы обычно прокладываете проводку.

С точки зрения общего дизайна такая схема соответствует модели-представлению-контроллеру при условии, что ваши представления выполняют только логику, связанную с представлением. Так, например, если у вас есть пользовательский прямоугольный вид, который можно смахнуть в любом месте, чтобы изменить положение булавки, а 2-е положение булавки влияет на некоторые другие системные настройки, вы были бы правы, поймав жест в представлении. , переместите вывод, а затем отправьте обновления о его положении делегату, который будет выполнять роль контроллера и передавать значение любым другим затронутым представлениям и модели.

Комментируя предлагаемые вами решения напрямую:

(1) это сосредоточит всю логику в одном контроллере; правильно ли это с точки зрения дизайна, зависит от степени, в которой вам приходится опрашивать свои пользовательские представления (в том смысле, что вы не хотите в конечном итоге рассматривать их как в основном данные, которые внешние субъекты должны знать, как манипулировать) и степень повторного использования логики.

(2) Я не уверен, что полностью понимаю предложение — для чего определен getViewController и как он знает, как реагировать? Если это сами UIViews, и контроллер представления должен сначала идентифицировать себя, я бы предложил просто принять шаблон делегата оптом, а не специализироваться на представлениях и контроллерах представлений, например. так как вы можете захотеть построить составные представления, которые связывают логику из нескольких подпредставлений.

(3) как правило, в init передаются такие вещи, которые класс действительно должен знать, чтобы иметь возможность инициализировать; вероятно, было бы лучше использовать обычное свойство для установки контроллера постфактум. Или сделайте его IBOutlet и подключите его так, чтобы это происходило автоматически через NIB.

person Tommy    schedule 14.07.2011
comment
Привет, Томми, спасибо за комментарий. Есть кое-что, чего я не понял: как вы написали, можно «поймать» жест в конкретном классе UIView. Поскольку у меня много таких классов, мне приходится координировать их жесты, устанавливая делегат жестов одному координатору (например, содержащему - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:). Должен ли это быть контроллер или я должен использовать для этого новый класс? - person kiessan; 14.07.2011
comment
Для 2) я имел в виду следующее. Каждый класс, наследуемый от UIView, имеет свой протокол, реализованный соответствующим ViewController для координации жестов. Когда эти классы хотят установить делегированные жесты (для координации жестов), они вызывают [leftSwipeRecognizer setDelegate:[delegate getViewController]];. Это делается всеми классами, унаследованными от UIView и включающими в себя жестРекогнизер. - person kiessan; 14.07.2011
comment
Я имел в виду, например. UIScrollView. Он фиксирует целую кучу жестов, включая смахивание, двойное касание и сведение пальцев, но, очевидно, это делегат для всех из них, он обрабатывает их все в некотором ориентированном на просмотр режиме, чтобы влиять на панорамирование и масштабирование, и передает только результаты своему делегату. Таким образом, координация и фильтрация множества различных жестов происходит в самом локальном представлении с уведомлением делегата о результате. - person Tommy; 14.07.2011