iOS - 拆分视图控制器 - 如何从主视图控制器内部获取指向详细视图控制器的指针(引用)?

时间:2014-08-18 08:30:39

标签: ios uisplitviewcontroller

iOS - 拆分视图控制器 - 如何从主视图控制器(较小的左侧控制器)内部获取指向详细视图控制器(较大的右侧控制器)的指针(参考)?

我的直觉告诉我主分割视图控制器应该引用细节视图控制器和我自己的主视图控制器,但我无法弄清楚如何获得它。

有什么想法吗?

2 个答案:

答案 0 :(得分:57)

拆分视图控制器 do 通过viewControllers属性引用其主控制器和详细视图控制器。

在iOS 7.x及更低版本中,viewControllers数组中应该只包含两个视图控制器对象。第一个对象是主视图控制器,第二个对象是详细视图控制器。

在iOS 8.0及更高版本中,viewControllers数组中至少有一个视图控制器对象 - 主(或“主”)视图控制器。如果第二个视图控制器对象在数组中,则它是详细信息(或“辅助”)视图控制器。折叠拆分视图控制器时,只有主视图控制器位于此数组中,扩展后它将包含主视图控制器和详细视图控制器。

您可以使用所有视图控制器的splitViewController属性来获取拆分视图控制器,然后使用viewControllers属性访问主视图控制器或详细视图控制器,如下所示:

<强>夫特:

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

<强>目标-C:

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

splitViewController属性通过向上走视图控制器层次结构并尝试查找调用视图控制器所在的任何拆分视图控制器来工作。如果视图控制器不在拆分视图控制器中,则属性为nil。它与navigationControllertabBarController视图控制器属性的工作方式相同。

您可以使用UISplitViewController上的Swift(或Objective-C中的类别)中的扩展程序来更轻松地访问主视图控制器和详细视图控制器,如此(将所有xx_替换为如果你使用的是Objective-C,你自己的前缀:

<强>夫特:

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

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

<强>目标-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

然后您可以使用这些属性:

<强>夫特:

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"
}

<强>目标-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";
}

答案 1 :(得分:1)

在UISplitViewController子类中创建一个属性:

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

根据Apple的文档,这有时应该返回nil,但根据我的经验,无论状态如何,它总是返回详细视图控制器。

此外,不要将此属性称为“detailViewController”而不是“_detailViewController” - Apple显然已经在引擎盖下使用该名称,并且它会弄乱您的UI。

UISplitViewController非常好,需要大量的清理和更正的文档...