Есть ли встроенный способ добраться от него UIView
до его UIViewController
? Я знаю, что вы можете получить от UIViewController
него UIView
через, [self view]
но мне было интересно, если есть обратная ссылка?
источник
Есть ли встроенный способ добраться от него UIView
до его UIViewController
? Я знаю, что вы можете получить от UIViewController
него UIView
через, [self view]
но мне было интересно, если есть обратная ссылка?
Так как это был принятый ответ в течение долгого времени, я чувствую, что должен исправить это с лучшим ответом.
Некоторые комментарии о необходимости:
Пример того, как это реализовать:
@protocol MyViewDelegate < NSObject >
- (void)viewActionHappened;
@end
@interface MyView : UIView
@property (nonatomic, assign) MyViewDelegate delegate;
@end
@interface MyViewController < MyViewDelegate >
@end
Представление взаимодействует с его делегатом (как UITableView
, например,), и ему все равно, реализовано ли оно в контроллере представления или в любом другом классе, который вы в конечном итоге используете.
Мой оригинальный ответ следующий: я не рекомендую это, ни остальные ответы, где прямой доступ к контроллеру представления достигнут
Нет встроенного способа сделать это. В то время как вы можете получить вокруг него, добавив IBOutlet
на UIView
и соединять их в Interface Builder, это не рекомендуется. Представление не должно знать о контроллере представления. Вместо этого вам следует поступить так, как предлагает @Phil M, и создать протокол, который будет использоваться в качестве делегата.
Используя пример, опубликованный Brock, я изменил его так, чтобы он был категорией UIView вместо UIViewController, и сделал его рекурсивным, чтобы любое подпредставление могло (надеюсь) найти родительский UIViewController.
Чтобы использовать этот код, добавьте его в новый файл класса (я назвал мой "UIKitCategories") и удалите данные класса ... скопируйте @interface в заголовок и @implementation в файл .m. Затем в вашем проекте #import "UIKitCategories.h" и используйте его в коде UIView:
источник
UIView
подклассUIResponder
.UIResponder
излагает метод-nextResponder
с реализацией, которая возвращаетnil
.UIView
переопределяет этот метод, как описано вUIResponder
(по некоторым причинам, а не вUIView
) следующим образом: если представление имеет контроллер представления, оно возвращается-nextResponder
. Если нет никакого контроллера представления, метод возвратит суперпредставление.Добавьте это в свой проект, и вы готовы к работе.
Теперь
UIView
есть рабочий метод для возврата контроллера представления.источник
UIView
иUIViewController
. Ответ Фила М с рекурсией - это путь.Я хотел бы предложить более легкий подход для обхода всей цепочки респондентов без добавления категории в UIView:
источник
Объединив несколько уже предоставленных ответов, я добавлю и мою реализацию:
Категория является частью моей статической библиотеки с поддержкой ARC, которую я поставляю в каждом приложении, которое создаю. Это было проверено несколько раз, и я не нашел никаких проблем или утечек.
PS: Вам не нужно использовать категорию, как я, если рассматриваемый вид является вашим подклассом. В последнем случае просто поместите метод в свой подкласс, и все готово.
источник
Хотя технически это можно решить, как рекомендует pgb , ИМХО, это недостаток дизайна. Представление не должно знать о контроллере.
источник
Я изменил de answer, чтобы я мог передать любое представление, кнопку, метку и т. Д., Чтобы получить его родитель
UIViewController
. Вот мой код.Редактировать версию Swift 3
Редактировать 2: - Быстрое расширение
источник
Не забывайте, что вы можете получить доступ к корневому контроллеру представления для окна, представлением которого является подпредставление. Оттуда, если вы, например, используете контроллер вида навигации и хотите добавить на него новый вид:
Однако сначала вам нужно будет правильно настроить свойство rootViewController окна. Делайте это при первом создании контроллера, например, в делегате приложения:
источник
[[self navigationController] view]
как это «основной» (под) вид окна, необходимо установитьrootViewController
свойство окна, которое немедленноnavigationController
контролирует «основной» вид.Хотя эти ответы являются технически правильными, включая Ushox, я думаю, что одобренный способ состоит в том, чтобы внедрить новый протокол или повторно использовать существующий. Протокол изолирует наблюдателя от наблюдаемого, что-то вроде вставки почтового отсека между ними. По сути, это то, что делает Габриэль через вызов метода pushViewController; представление «знает», что это правильный протокол, чтобы вежливо попросить ваш navigationController выдвинуть представление, поскольку viewController соответствует протоколу navigationController. Хотя вы можете создать свой собственный протокол, просто используйте пример Габриэля и повторно используйте протокол UINavigationController.
источник
Я наткнулся на ситуацию, когда у меня есть небольшой компонент, который я хочу использовать повторно, и добавил некоторый код в само повторно используемое представление (это на самом деле не намного больше, чем кнопка, открывающая a
PopoverController
).В то время как это работает отлично в IPad (в
UIPopoverController
самых подарках, для них не нуждается указания наUIViewController
), получая тот же код для работы средства вдруг вашихpresentViewController
от вашегоUIViewController
. Вроде противоречиво верно?Как упоминалось ранее, это не лучший подход, чтобы иметь логику в вашем UIView. Но было действительно бесполезно заключать несколько строк кода, необходимых в отдельный контроллер.
В любом случае, вот быстрое решение, которое добавляет новое свойство к любому UIView:
источник
Я не думаю, что это «плохая» идея выяснить, кто является контроллером представления в некоторых случаях. Что может быть плохой идеей, так это сохранить ссылку на этот контроллер, поскольку он может меняться так же, как меняются суперпредставления. В моем случае у меня есть геттер, который пересекает цепочку респондента.
//.час
//.m
источник
Простейший цикл do while для поиска viewController.
источник
Swift 4
(более кратко, чем другие ответы)
Мой случай использования , для которого мне нужно открыть представление первых
UIViewController
: у меня есть объект , который оборачивается вокругAVPlayer
/AVPlayerViewController
и я хочу , чтобы обеспечить простойshow(in view: UIView)
метод , который будет встраиватьAVPlayerViewController
вview
. Для этого мне нужно получить доступview
«SUIViewController
.источник
Это не дает прямого ответа на вопрос, а скорее делает предположение о цели вопроса.
Если у вас есть представление и в этом представлении вам нужно вызвать метод для другого объекта, например, скажем, контроллера представления, вы можете вместо этого использовать NSNotificationCenter.
Сначала создайте строку уведомления в заголовочном файле
По вашему мнению позвоните postNotificationName:
Затем в вашем контроллере представления вы добавляете наблюдателя. Я делаю это в viewDidLoad
Теперь (также в том же контроллере представления) реализуйте свой метод copyString: как показано в @selector выше.
Я не говорю, что это правильный способ сделать это, просто кажется чище, чем запуск цепочки первого респондента. Я использовал этот код для реализации UIMenuController в UITableView и передачи события обратно в UIViewController, чтобы я мог что-то сделать с данными.
источник
Это, конечно, плохая идея и неправильный дизайн, но я уверен, что нам всем понравится решение Swift с лучшим ответом, предложенным @Phil_M:
Если вы намереваетесь делать простые вещи, такие как показ модального диалога или отслеживание данных, это не оправдывает использование протокола. Я лично храню эту функцию в служебном объекте, вы можете использовать ее из всего, что реализует протокол UIResponder:
Все кредиты @Phil_M
источник
Может быть, я опоздал сюда. Но в этой ситуации мне не нравится категория (загрязнение). Я люблю так:
источник
Более быстрое решение
источник
sequence
немного). Так что, если «swifty» означает «более функциональный», то я думаю, что это более «swifty».Обновленная версия для swift 4: Спасибо за @Phil_M и @ paul-slm
источник
Версия Swift 4
Пример использования
источник
Два решения от Swift 5.2 :
return
Теперь не нужно ключевое слово nowРешение 1:
Решение 2:
источник
На ответ Фила:
В строке:
id nextResponder = [self nextResponder];
если self (UIView) не является подпредставлением представления ViewController, если вы знаете иерархию self (UIView), вы также можете использовать:id nextResponder = [[self superview] nextResponder];
...источник
Мое решение, вероятно, было бы сочтено фальшивым, но у меня была похожая ситуация с mayoneez (я хотел переключать представления в ответ на жест в EAGLView), и я получил контроллер представления EAGL следующим образом:
источник
EAGLViewController *vc = [(EAGLAppDelegate *)[UIApplication sharedApplication].delegate viewController];
.ClassName *object
- со звездочкой.Я думаю, что есть случай, когда наблюдателю необходимо информировать наблюдателя.
Я вижу аналогичную проблему, когда UIView в UIViewController реагирует на ситуацию, и ему необходимо сначала сказать своему родительскому контроллеру представления скрыть кнопку возврата, а затем по завершении сказать родительскому контроллеру представления, что ему нужно выскочить из стека.
Я пытался это с делегатами без успеха.
Я не понимаю, почему это должно быть плохой идеей?
источник
Другой простой способ - иметь свой собственный класс представления и добавить свойство контроллера представления в класс представления. Обычно контроллер представления создает представление, и именно здесь контроллер может установить для себя свойство. По сути, это вместо того, чтобы искать (с небольшим взломом) контроллер, иметь контроллер, чтобы настроить себя на представление - это просто, но имеет смысл, потому что именно контроллер «контролирует» представление.
источник
Если вы не собираетесь загружать это в App Store, вы также можете использовать приватный метод UIView.
источник
источник
Чтобы получить контроллер данного представления, можно использовать цепочку UIFirstResponder.
источник
Если ваш rootViewController - UINavigationViewController, который был установлен в классе AppDelegate, тогда
Где c требуется вид контроллеров класса.
ИСПОЛЬЗОВАНИЕ:
источник
Выхода нет.
Что я делаю, это передаю указатель UIViewController на UIView (или соответствующее наследование). Извините, я не могу помочь с подходом IB к проблеме, потому что я не верю в IB.
Чтобы ответить первому комментатору: иногда вам нужно знать, кто вам звонил, потому что он определяет, что вы можете сделать. Например, с базой данных вы можете иметь только права на чтение или чтение / запись ...
источник