Подтвердить что ты не робот

IOS - Split View Controller - Как получить указатель (ссылку) на контроллер подробных представлений изнутри главного контроллера просмотра?

iOS - Split View Controller - Как получить указатель (ссылку) на контроллер подробных представлений (больше справа) изнутри главного контроллера просмотра (меньший слева)?

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

Любые мысли?

4b9b3361

Ответ 1

У контроллеров Split view есть ссылки на их главные и подробные контроллеры представлений с помощью свойства viewControllers.

В iOS 7.x и ниже массив viewControllers должен иметь ровно два объекта контроллера представления. Первым объектом является контроллер главного представления, а второй объект - это контроллер подробного представления.

В iOS 8.0 и выше массив viewControllers имеет в нем как минимум один объект контроллера представления - главный (или первичный) контроллер представления. Если в массиве находится объект контроллера второго представления, он является контроллером представления деталей (или "вторичного" ). Когда контроллер разделенного представления свернут, в этом массиве находится только главный контроллер просмотра, а при его расширении он будет содержать как главный, так и диспетчер представлений деталей.

Вы можете использовать свойство splitViewController для всех контроллеров представления, чтобы получить контроллер разделенного представления, и оттуда использовать свойство viewControllers для доступа к вашим основным или дополнительным контроллерам представлений, например:

Swift:

let masterVC = self.splitViewController?.viewControllers.first
let detailVC = (self.splitViewController?.viewControllers.count > 1) ? self.splitViewController?.viewControllers[1] : nil

Objective-C:

UIViewController *masterVC = [self.splitViewController.viewControllers firstObject];
UIViewController *detailVC;
if (self.splitViewController.viewControllers.count > 1) {
    detailVC = self.splitViewController.viewControllers[1];
}

Свойство splitViewController работает, идя вверх по иерархии диспетчера представлений и пытаясь найти любой контроллер разделенного представления, в котором находится контроллер вызова. Если контроллер представления не находится в контроллере с разделенным представлением, тогда свойство nil. Он работает так же, как свойства контроллера просмотра navigationController и tabBarController.

Вы можете упростить доступ к главному и подробному диспетчерам представлений с помощью расширения в Swift (или категории в Objective-C) на UISplitViewController, например, (заменив все xx_ собственным префиксом, re с помощью Objective-C):

Swift:

extension UISplitViewController {
    var primaryViewController: UIViewController? {
        return self.viewControllers.first
    }

    var secondaryViewController: UIViewController? {
        return self.viewControllers.count > 1 ? self.viewControllers[1] : nil
    }
}

Objective-C:

// UISplitViewController+ChildViewControllerAccess.h
@interface UISplitViewController (ChildViewControllerAccess)

@property (nonatomic, readonly) UIViewController *xx_primaryViewController;
@property (nonatomic, readonly) UIViewController *xx_secondaryViewController;

@end

// UISplitViewController+ChildViewControllerAccess.m
@implementation UISplitViewController (ChildViewControllerAccess)

- (UIViewController *)xx_primaryViewController
{
    return self.viewControllers.firstObject;
}

- (UIViewController *)xx_secondaryViewController
{
    return self.viewControllers.count > 1 ? self.viewControllers[1] : nil;
}

@end

Затем вы можете использовать эти свойства следующим образом:

Swift:

func someFunctionInSomeViewControllerClass {
    // Get the primary and secondary view controllers if
    // this view controller is in a split view controller.
    // These will be nil if this view controller is not a
    // descendant of a split view controller.
    var primaryVC = self.splitViewController?.primaryViewController
    var secondaryVC = self.splitViewController?.secondaryViewController

    // Do something with them
    primaryVC?.title = "This is the primary VC"
    secondaryVC?.title = "This is the secondary VC"
}

Objective-C:

#import "UISplitViewController+ChildViewControllerAccess.h"

[...]

- (void)someMethodInSomeViewControllerClass
{
    // Get the primary and secondary view controllers if
    // this view controller is in a split view controller.
    // These will be nil if this view controller is not a
    // descendant of a split view controller.
    UIViewController *primaryVC = self.splitViewController.xx_primaryViewController;
    UIViewController *secondaryVC = self.splitViewController.xx_secondaryViewController;

    // Do something with them
    primaryVC.title = @"This is the primary VC";
    secondaryVC.title = @"This is the secondary VC";
}

Ответ 2

Создайте свойство в подклассе UISplitViewController:

var _detailViewController: UIViewController? {
    get {
        if viewControllers.count > 1 {
            return viewControllers[1] as? UIViewController
        }
        return nil
    }
}

Согласно документации Apple, это иногда должно возвращать нуль, но, по моему опыту, он всегда возвращает контроллер подробного представления, независимо от состояния.

Кроме того, не называйте это свойство "detailViewController" вместо "_detailViewController" - Apple, по-видимому, уже использует это имя под капотом, и оно будет работать с вашим пользовательским интерфейсом.

UISplitViewController действительно hokey и нуждается в большой очистке и исправленной документации...