Откройте UISplitViewController для просмотра мастера, а не детали

У меня есть интерфейс с разделенным изображением с целевым приложением iPhone 6. При первом запуске приложения открывается подробный вид; Я бы хотел, чтобы он открылся для Мастера. Я пробовал:

self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryOverlay

Что было предложено в другом месте qaru.site/info/551707/..., но, похоже, он ничего не делает и не открывает мастер-представление при запуске. Я также попытался добавить следующую строку в свой AppDelegate:

splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:

Но, несмотря на возвращение true или false (Другой вопрос о переполнении стека), я не имел успеха.

Я запускал пример приложения Master-Detail в Xcode и загружался в представление Master на основе splitViewController: call return false; однако я не уверен, как сделать эту работу более сложной.

Ответ 1

Swift

UISplitViewController отображает главный вид выше детализации в книжной ориентации - это не отображение основного вида, а представление подробного представления во всю ширину под основным видом.

UISplitViewController в портретной ориентации на iPhone показывает детализацию VC вместо основной о принципе механизма свертывания.

Этот настоящий адрес адресов:

  • Мастер → Деталь (Компактная ширина)
    • iPhone 4s, 5, 5s, SE, 6, 6s, 7 (любая ориентация)
    • iPod Touch
    • любой айфон плюс (портрет)
  • бок о бок (все другие размеры)
    • IPad
    • любой iPhone Plus (альбомная)

Вы должны установить preferredDisplayMode. Вы бы хотели .primaryVisible, если бы он существовал! Используя .allVisible, iOS выбирает Detail, если подходит только 1 вид (Компактная ширина); в этом размере код ниже выберет Master.

Хитрость заключается в том, чтобы изменить preferredDisplayMode на .allVisible и вернуть true в collapseSecondary:onto.

class PrimarySplitViewController: UISplitViewController,
                                  UISplitViewControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
        self.preferredDisplayMode = .allVisible
    }

    func splitViewController(
             _ splitViewController: UISplitViewController,
             collapseSecondary secondaryViewController: UIViewController,
             onto primaryViewController: UIViewController) -> Bool {
        // Return true to prevent UIKit from applying its default behavior
        return true 
    }
}

Ответ 2

Шаг 1 - Открыть MasterViewController

Шаг 2 - убедитесь, что в представлении таблицы есть протокол UISplitViewControllerDelegate. Например:

class ListVC: UITableViewController,UISplitViewControllerDelegate {}

Шаг 3 - добавьте его в ViewDidLoad

splitViewController?.delegate = self

Шаг 4. Затем переопределите этот метод, чтобы сказать, что контроллер главного представления должен всегда сворачиваться на контроллер подробного представления:

func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool {
    return true
}

Ответ 3

При первом запуске приложения открывается подробный вид; Я бы хотел, чтобы он открылся для просмотра мастера

Предполагая, что вы хотите это только при первом запуске, но не всегда; например, в том случае, если мастер-представление показывает пустой набор данных; то решение будет таким же, как и в шаблоне Master-Detail:

func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool {
    guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
    guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
    if topAsDetailController.detailItem == nil {
        // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return true
    }
    return false
}

Ответ 4

Это старый вопрос, и ни один из ответов не был для Задачи C, и даже когда я портировал ответы Swift, ни один из них не работал для меня. Один был близко, @SwiftArchitect.

Но он порекомендовал установить режим содержимого в .allVisible (UISplitViewControllerDisplayModeAllVisible в Objective C) - это заставляет главное представление постоянно отображаться, разделяя представление на главное с одной стороны, детали с другой. Это круто, но ОП попросил специально отобразить главное представление при первом запуске, что мне и нужно было сделать.

Изменением было использование UISplitViewControllerDisplayModePrimaryOverlay для режима отображения.

Этот ответ для Xcode 9.4.1, цель развертывания 11.4.

Вот MasterViewController.h - вам нужно добавить UISplitViewControllerDelegate в объявлении протоколов:

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import "MasterDetailDemo+CoreDataModel.h"

@class DetailViewController;

@interface MasterViewController : UITableViewController
<UISplitViewControllerDelegate,
NSFetchedResultsControllerDelegate>

@property (strong, nonatomic) DetailViewController *detailViewController;

@property (strong, nonatomic) NSFetchedResultsController<Event *> *fetchedResultsController;
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;

@end

И затем в вашем MasterViewController.m вам нужно установить делегат контроллера разделенного представления и режим содержимого в ViewDidLoad, а затем вместе с ответом @SwiftArchitect также добавить метод делегата контроллера разделенного представления:

- (void)viewDidLoad {

    [super viewDidLoad];

    // needed to "slide out" MasterView on startup on iPad
    self.splitViewController.delegate = self;
    self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;

    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];

    self.navigationItem.rightBarButtonItem = addButton;

    self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
}

// split view delegate method
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
    return true;
}

ПРИМЕЧАНИЕ. После некоторого тестирования я обнаружил, что метод делегирования с разделенным представлением и протокол с разделенным представлением не были необходимы. Без этого, похоже, работает точно так же. Возможно, это результат изменений в iOS, так как вопрос был первоначально задан и получен ответ.

Я получил это работает нормально, просто поместив эту строку в мой метод ViewDidLoad:

self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModePrimaryOverlay;

Ответ 5

Или просто унаследуйте от UISplitViewController и используйте этот новый класс в раскадровке (на основе ответа SwiftArchitect):

class MasterShowingSplitViewController :UISplitViewController, UISplitViewControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        self.delegate = self
        self.preferredDisplayMode = .allVisible
    }

    func splitViewController(
        _ splitViewController: UISplitViewController,
        collapseSecondary secondaryViewController: UIViewController,
        onto primaryViewController: UIViewController) -> Bool {
        // Return true to prevent UIKit from applying its default behavior
        return true
    }
}