Текущее UIViewController
на экране необходимо для ответа на push-уведомления от APN, установив некоторые виды значков. Но как я могу получить UIViewController
метод in application:didReceiveRemoteNotification
: of AppDelegate.m
?
Я попытался использовать self.window.rootViewController
для получения текущего отображения UIViewController
, это может быть UINavigationViewController
контроллер представления или какой-то другой. И я обнаружил, что visibleViewController
свойство UINavigationViewController
можно использовать для вывода UIViewController
на экран. Но что я мог сделать, если это не а UINavigationViewController
?
Любая помощь приветствуется! Соответствующий код выглядит следующим образом.
AppDelegate.m
...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//I would like to find out which view controller is on the screen here.
UIViewController *vc = [(UINavigationViewController *)self.window.rootViewController visibleViewController];
[vc performSelector:@selector(handleThePushNotification:) withObject:userInfo];
}
...
ViewControllerA.m
- (void)handleThePushNotification:(NSDictionary *)userInfo{
//set some badge view here
}
UIView
экземпляра нет.rootViewController
это не обязательно показан в данный момент контроллер. Это просто наверху иерархии представлений.Мне всегда нравятся решения, которые включают категории, поскольку они закреплены и могут быть легко использованы повторно.
Итак, я создал категорию в UIWindow. Теперь вы можете вызвать visibleViewController в UIWindow, и это даст вам контроллер видимого представления, выполнив поиск по иерархии контроллеров. Это работает, если вы используете контроллер навигации и / или панели вкладок. Если у вас есть другой тип контроллера, пожалуйста, дайте мне знать, и я могу его добавить.
UIWindow + PazLabs.h (файл заголовка)
UIWindow + PazLabs.m (файл реализации)
Быстрая версия
источник
Простое расширение для UIApplication в Swift (заботится даже о moreNavigationController внутри
UITabBarController
на iPhone) :Простое использование:
Отлично работает :-)
ОБНОВЛЕНИЕ для чистого кода:
источник
Вы также можете отправить уведомление через NSNotificationCenter. Это позволит вам справиться с рядом ситуаций, в которых обход иерархии контроллеров представления может быть затруднительным - например, когда представлены модальные окна и т. Д.
Например,
В каждом из ваших контроллеров просмотра:
Вы также можете использовать этот подход для управления инструментами, которые должны обновляться при получении уведомления и используются несколькими контроллерами представления. В этом случае обработайте вызовы наблюдателя добавления / удаления в методах init и dealloc соответственно.
источник
addObserver:bar
внутриviewDidLoad
? Мне нужно заменить наself
?Код
Вот подход, использующий отличный синтаксис switch-case в Swift 3/4/5 :
Основная идея такая же, как и в ответе zirinisp, просто используется синтаксис, похожий на Swift 3+.
использование
Вероятно, вы захотите создать файл с именем
UIWindowExtension.swift
. Убедитесь, что он включаетimport UIKit
инструкцию, а теперь скопируйте приведенный выше код расширения .На стороне вызова его можно использовать без какого-либо конкретного контроллера представления :
Или, если вы знаете, что ваш контроллер видимого представления доступен с определенного контроллера представления :
Я надеюсь, что это помогает!
источник
presentingViewController
и передатьpresentingViewController.presentedViewController
в качестве параметра рекурсивному методу.UIWindow.visibleViewController(from: presentedViewController)
что вместо этого должно бытьUIWindow.visibleViewController(from: presentingViewController.presentedViewController)
?presentedViewController
иviewController
это тот же объект, и он будет вызывать метод сам с собой, пока стек не переполнится (каламбур). Так и будетcase let presentingViewController where viewController?.presentedViewController != nil: return UIWindow.visibleViewController(from: presentingViewController.presentedViewController)
Я обнаружил, что iOS 8 все испортила. В iOS 7 есть новое
UITransitionView
в иерархии представлений всякий раз, когда у вас есть модальное представлениеUINavigationController
. В любом случае, вот мой код, который находит, получает самый верхний VC. ВызовgetTopMostViewController
должен вернуть VC, который вы должны иметь возможность отправить сообщение вродеpresentViewController:animated:completion
. Его цель - предоставить вам VC, который вы можете использовать для представления модального VC, поэтому он, скорее всего, остановится и вернется в классы контейнера, такие как,UINavigationController
а НЕ VC, содержащийся в них. Не должно быть сложно адаптировать код и для этого. Я тестировал этот код в различных ситуациях в iOS 6, 7 и 8. Сообщите мне, если вы обнаружите ошибки.источник
Намного меньше кода, чем у всех других решений:
Версия Objective-C:
Версия Swift 2.0: (кредит принадлежит Стиву Б.)
Работает в любом месте вашего приложения, даже с модальными окнами.
источник
UINavigationController
имеет собственных дочерних элементов.Ответ zirinisp на Swift:
Использование:
источник
as!
иnavigationController.visibleViewController!
для Swift 2.0Укажите заголовок для каждого ViewController, а затем получите заголовок текущего ViewController с помощью кода, приведенного ниже.
Затем проверьте это по своему заголовку, как это
источник
self.title = myPhotoView
Моя лучше! :)
источник
Почему бы просто не обработать код push-уведомления в делегате приложения? Это напрямую связано с представлением?
Вы можете проверить, отображается ли в настоящее время представление UIViewController, проверив, имеет ли его
window
свойство представления значение. Подробнее здесь .источник
Просто дополнение к ответу @zirinisp.
Создайте файл, назовите его
UIWindowExtension.swift
и вставьте следующий фрагмент:Используйте его где угодно как:
Спасибо @zirinisp.
источник
Что касается сообщения NSNotificationCenter выше (извините, не могу понять, где разместить под ним комментарий ...)
В случае, если некоторые получали ошибку - [NSConcreteNotification allKeys]. Измените это:
к этому:
источник
Это сработало для меня. У меня много целей с разными контроллерами, поэтому предыдущие ответы не сработали.
сначала вы хотите это внутри своего класса AppDelegate:
тогда в вашей функции
источник
Это лучший способ, который я пробовал. Если это кому-то поможет ...
источник
С помощью этого вы можете легко получить контроллер верхнего представления, например
Следует отметить, что если в данный момент отображается UIAlertController,
UIApplication.topMostViewController
он вернетUIAlertController
.источник
Swift 2.0 версия ответа jungledev
источник
Я создал категорию
UIApplication
сvisibleViewControllers
недвижимостью. Основная идея довольно проста. Я обвелviewDidAppear
иviewDidDisappear
методыUIViewController
. ВviewDidAppear
методе viewController добавлен в стек. ВviewDidDisappear
методе viewController удаляется из стека.NSPointerArray
используется вместоNSArray
хранения слабыхUIViewController
ссылки. Этот подход работает для любой иерархии viewControllers.UIApplication + VisibleViewControllers.h
UIApplication + VisibleViewControllers.m
https://gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0
Версия Swift 3
UIApplication + VisibleViewControllers.swift
https://gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399
источник
Всегда проверяйте конфигурацию сборки, если вы запускаете приложение с отладкой или выпуском.
ВАЖНОЕ ПРИМЕЧАНИЕ: вы не сможете протестировать его, не запустив приложение в режиме отладки.
Это было мое решение
источник