Как использовать UISplitViewController в качестве модального контроллера представления? - PullRequest
7 голосов
/ 19 января 2011

Я пытаюсь отобразить UISplitViewController, представляя его в качестве модального контроллера просмотра в моем приложении для iPad. Мне удается отобразить его, но по какой-то причине слева от модального окна есть промежуток размера строки состояния, который также сохраняется при изменении ориентации.

alt text

Кто-нибудь знает, почему это происходит? Или если это вообще возможно? Может быть, я просто копаю себе огромную яму.

Ответы [ 6 ]

8 голосов
/ 14 ноября 2013

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

Однако иногда также не очень удобно изменять большую часть вашей кодовой базы и делать UISplitViewController начальным объектом просто для того, чтобы его функциональность была запущена и работала.

В свою очередь, есть способ сделать всех счастливыми (включая рекомендации Apple). Решение, которое я нашел лучше всего, состояло в том, чтобы использовать UISplitViewController в обычном режиме, но при необходимости показать / отклонить, используйте следующий подход:

-(void)presentWithMasterViewController: (UIViewController *) thisMasterViewController
   andDetailViewController: (UIViewController *) thisDetailViewController
                        completion:(void(^)(void))completion
{
    masterViewController = thisMasterViewController;
    detailViewController = thisDetailViewController;

    [self setViewControllers:[NSArray arrayWithObjects:masterViewController, detailViewController, nil]];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;

    self.window.rootViewController = self;

    [self.window makeKeyAndVisible];

    if(completion)
        completion();
    }

-(void)dismissViewControllerWithCompletion:(void (^)(void))completion
 {
     self.window = nil;
     masterViewController = nil;
     detailViewController = nil;
     if(completion)
         completion();
 }

Где "window" - это свойство вашего подкласса UISplitViewController. А система позаботится обо всем остальном!

Для удобства / ссылки я загрузил это как подкласс UISplitViewController в gitHub:

ModalSplitViewController

- ПРИМЕР, КАК ИСПОЛЬЗОВАТЬ -

    mySplitViewController = [[ModalSplitViewController alloc] init];
    mySplitViewController.delegate = self;

    [mySplitViewController presentWithMasterViewController:masterViewController andDetailViewController:detailViewController completion:nil];

    // when done:

    [mySplitViewController dismissViewControllerWithCompletion:nil];
    mySplitViewController = nil;

Примечание: я полагаю, что большая часть путаницы проистекает из того факта, что пример использования UISplitView из документации Apple использует окно создан в приложении Delegate, и за то, что большинство людей не так знаком с концепцией окна - потому что нам обычно не нужно to (они создаются один раз в StoryBoards или шаблонном коде).

Кроме того, если вы делаете восстановление состояния, не следует забудьте, что программно созданные UIViewControllers не будут автоматически восстанавливаться системой.

6 голосов
/ 19 января 2011

Акция UISplitViewController была разработана для использования только в качестве контроллера корневого представления. Представление одного из них идет вразрез с руководящими принципами Apple Human Interface Guidelines и с большой вероятностью будет отклонено группой проверки приложений. Кроме того, вы можете получить сообщение об ошибке:

Приложение пыталось представить контроллеры Split View модально

3 голосов
/ 05 апреля 2012

Я согласен с Эваном в том, что это немного не в цвете для Apple, но я смог завершить рабочую версию этого с помощью следующего решения:

UISplitViewController *splitVC = [[UISplitViewController alloc] init];
    splitVC.delegate = VC2;
    splitVC.viewControllers = [NSArray arrayWithObjects:navcon1, navcon2, nil];

    UINavigationController *splitNavCon = [[UINavigationController alloc] init];
    splitNavCon.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [splitNavCon.view addSubview:splitVC.view];
    VC2.splitParentViewController = splitNavCon;

    [self presentViewController:splitNavCon animated:YES completion:nil];

.кнопка в новом UISplitViewController, который был представлен модально на экране.

Вы заметите, что я фактически передаю VC2 (делегат UISplitViewController) его родительский UINavigationController.Это был лучший способ, который я обнаружил, я мог отменить UISplitViewController из VC2:

[splitParentViewController dismissViewControllerAnimated:YES completion:nil];
3 голосов
/ 15 апреля 2011

Технически, это то, что я сделал:

1 / Подкласс UIViewController т.е.@interface aVC: UIViewController

2 / В viewDidLoad установите splitViewController, т.е.aSplitVC

3 / Затем self.view = aSplitVC.view

В конце концов, представьте aVC как modalViewController

0 голосов
/ 21 сентября 2015

Этот ответ на самом деле не верен, потому что он недействителен с iOS8, и если вам нужно поддерживать даже iOS7, вы можете сделать это так, как если бы вы фактически установили модально UIViewController с контейнером SplitView.

let mdSplitView = self.storyboard?.instantiateViewControllerWithIdentifier("myDataSplitView") as! MyData_SplitVC
    self.addChildViewController(mdSplitView)

    mdSplitView.view.bounds = self.view.bounds
    self.view.addSubview(mdSplitView.view)
    mdSplitView.didMoveToParentViewController(self)
0 голосов
/ 30 июля 2014

Я полагаю, что можно сделать наоборот: вместо настраиваемого контроллера, представляющего контроллер разбиения, можно настроить контроллер разделения в качестве корневого контроллера окна в раскадровке, а поверх его представления можно добавить свой настраиваемый контроллер (т.е., экран входа в систему) и удалите его с экрана (например, removeFromSuperview), когда это необходимо.

...