web-dev-qa-db-fra.com

iOS - Split View Controller - Comment puis-je obtenir un pointeur (référence) vers le Detail View Controller depuis l'intérieur du Master View Controller?

iOS - Split View Controller - Comment puis-je obtenir un pointeur (référence) vers le Detail View Controller (le plus grand à droite) depuis l'intérieur du Master View Controller (le plus petit à gauche)?

Mon instinct me dit que le contrôleur principal de vue fractionnée devrait avoir une référence au contrôleur de vue détaillée et à mon propre contrôleur de vue principal, mais je ne peux pas comprendre comment l'obtenir.

Des pensées?

25
unom

Les contrôleurs de vue fractionnée ont des références à leurs contrôleurs de vue maître et détail, via la propriété viewControllers.

Dans iOS 7.x et versions antérieures, le tableau viewControllers doit contenir exactement deux objets de contrôleur de vue. Le premier objet est le contrôleur de vue principal et le deuxième objet est le contrôleur de vue de détail.

Dans iOS 8.0 et supérieur, le tableau viewControllers contient au moins un objet contrôleur de vue - le contrôleur de vue maître (ou "principal"). Si un deuxième objet contrôleur de vue se trouve dans le tableau, il s'agit du contrôleur de vue détaillé (ou "secondaire"). Lorsque le contrôleur de vue fractionnée est réduit, seul le contrôleur de vue maître se trouve dans ce tableau et, une fois développé, il contiendra à la fois le contrôleur de vue maître et le contrôleur de vue de détail.

Vous pouvez utiliser la propriété splitViewController de tous les contrôleurs de vue pour obtenir votre contrôleur de vue fractionnée, et à partir de là, utilisez la propriété viewControllers pour accéder à vos contrôleurs de vue maître ou de détail, comme ceci:

Swift:

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

Objectif-C:

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

La propriété splitViewController fonctionne en remontant la hiérarchie du contrôleur de vue et en essayant de trouver tout contrôleur de vue divisé dans lequel se trouve le contrôleur de vue appelant. Si le contrôleur de vue n'est pas dans un contrôleur de vue divisé, la propriété est nil. Il fonctionne de la même manière que les propriétés du contrôleur de vue navigationController et tabBarController.

Vous pouvez faciliter l'accès aux contrôleurs de vue principale et détaillée en utilisant une extension dans Swift (ou une catégorie dans Objective-C) sur UISplitViewController, comme cela (en remplaçant tous les xx_ avec votre propre préfixe si vous utilisez Objective-C):

Swift:

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

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

Objectif-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

Vous pouvez ensuite utiliser ces propriétés comme suit:

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

Objectif-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";
}
59
TylerTheCompiler

Créez une propriété dans votre sous-classe UISplitViewController:

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

Selon la documentation d'Apple, cela devrait parfois retourner nul, mais d'après mon expérience, cela renvoie toujours le contrôleur de vue de détail, quel que soit l'état.

En outre, n'appelez pas cette propriété "detailViewController" au lieu de "_detailViewController" - Apple utilise apparemment déjà ce nom sous le capot, et il perturbera votre interface utilisateur.

UISplitViewController est vraiment hokey et a besoin de beaucoup de nettoyage et de documentation corrigée ...

1
user1021430