Я закончил очень хакерским (но работающим) способом. Это могло сработать не во всех сценариях, но в моем сработало. Я сохранил представление как есть, и не коснулся ни одного представления или контроллера.
Во-первых, у меня сейчас отображается самый верхний контроллер представления. Я использовал код из iPhone - Как найти самый верхний view controller и немного изменил его для обработки случаев контроллера навигации и панели вкладок:
+ (UIViewController*) topmostControllerForViewController:(__kindof UIViewController*)topController
{
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
if([topController isKindOfClass:[UINavigationController class]]){
UINavigationController *navController = topController;
return [self topmostControllerForViewController:navController.visibleViewController];
}
if([topController isKindOfClass:[UITabBarController class]]){
UITabBarController *tabController = topController;
return [self topmostControllerForViewController:tabController.selectedViewController];
}
return topController;
}
+ (UIViewController*) topmostController
{
__kindof UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
return [self topmostControllerForViewController:topController];
}
Затем я создал контроллер представления без представления (view
равно nil
). В этом init
методе (не работает при первом вызове, если ввести viewDidLoad:
, поскольку он вызывается в процессе перехода, и уже слишком поздно), я добавил следующее:
self.modalPresentationCapturesStatusBarAppearance = YES;
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
Этот код позволял моему «фиктивному» контроллеру представления (меньше) обрабатывать весь контекст презентации, включая внешний вид строки состояния и то, что происходит с другими контроллерами представлений, когда она представлена. При представлении в текущем контексте контроллер представления сзади не удаляется из иерархии представлений. Если я этого не сделаю, он будет удален, а экран станет черным (поскольку у меня нет представления, и я хочу, чтобы отображался предыдущий контроллер представления).
Все идет нормально. Затем я обычно отображал свою панель, но одновременно представлял этот контроллер представления модально без какого-либо представления. Поскольку контроллер представления не имел представления и был представлен в текущем контексте, он визуально не отображался никаким образом, но, поскольку это было модальное представление, а фиктивный контроллер представления был настроен на захват стиля представления, он запускал iOS чтобы запросить у моего приложения стиль строки состояния. Я просто настроил свой стиль строки состояния, как я хотел, в методах контроллера представления.
Была небольшая проблема. Когда я представил новый контроллер представления, система добавила UITransitionView
поверх моего предыдущего контроллера представления. Если бы существовал реальный вид, он был бы поверх вида перехода. Представление перехода полностью прозрачно, но в нем включено взаимодействие с пользователем и фиксируются все события касания, в результате чего мое приложение не отвечает, пока я не отключу контроллер. Мне нужен был мой предыдущий контроллер представления для получения событий касания. Я копал глубже и нашел, где модальная презентация добавляет представление перехода, и удалил его при представлении контроллера представления после завершения анимации перехода:
for (UIView *view in self.subviews) {
NSString *className = NSStringFromClass([view class]);
if([className hasPrefix:@"UIT"] && className.length == 16){
//this must be UITransitionView, but I'm not using it directly since it may interfere with private API usage and get app rejected by Apple.
//now, we need to find another transition view inside this and remove it
for (UIView *innerView in view.subviews) {
className = NSStringFromClass([innerView class]);
if([className hasPrefix:@"UIT"] && className.length == 16){
//this is the transition view that we need to remove
[innerView removeFromSuperview];
}
}
}
}
Поскольку UITransitionView
- это частный тип представления, и я не уверен, вызывает ли он проблему с App Store, я выполнил эвристическую проверку UITransitionView
, проверив первые буквы UIT
и проверив длину имени класса. Это не пуленепробиваемое устройство, но похоже, что оно работает и вряд ли вернет ложное срабатывание.
Теперь все работает как положено. Это взломано и может сломаться в будущем, особенно если модальное представление изменится под капотом. Но будьте уверены, это работает.
person
Can Poyrazoğlu
schedule
19.03.2017