ビューが与えられた場合、そのviewControllerを取得するにはどうすればいいですか? 質問する

ビューが与えられた場合、そのviewControllerを取得するにはどうすればいいですか? 質問する

へのポインタがありますUIView。その にはどうやってアクセスするのでしょうかUIViewController?[self superview]は別の でありUIView、 ではないですUIViewControllerよね?

ベストアンサー1

UIResponderのドキュメントよりnextResponder:

UIResponder クラスは、次のレスポンダーを自動的に保存または設定せず、代わりにデフォルトで nil を返します。サブクラスは、次のレスポンダーを設定するためにこのメソッドをオーバーライドする必要があります。UIView は、それを管理する UIViewController オブジェクト (存在する場合) またはそのスーパービュー (存在しない場合) を返すことによってこのメソッドを実装します。; UIViewController はビューのスーパービューを返すことによってメソッドを実装します。UIWindow はアプリケーション オブジェクトを返し、UIApplication は nil を返します。

したがって、ビューがnextResponderタイプになるまで を再帰するとUIViewController、任意のビューの親 viewController が得られます。

ただし、ない親ビューコントローラがあります。ただし、ビューが viewController のビューのビュー階層の一部ではない場合に限ります。

Swift 3とスウィフト4.1拡大:

extension UIView {
    var parentViewController: UIViewController? {
        // Starts from next (As we know self is not a UIViewController).
        var parentResponder: UIResponder? = self.next
        while parentResponder != nil {
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
            parentResponder = parentResponder?.next
        }
        return nil
    }
}

Swift 2 拡張機能:

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self.nextResponder()
        while parentResponder != nil {
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
            parentResponder = parentResponder!.nextResponder()
        }
        return nil
    }
}

Objective-C カテゴリ:

@interface UIView (mxcl)
- (UIViewController *)parentViewController;
@end

@implementation UIView (mxcl)
- (UIViewController *)parentViewController {
    UIResponder *responder = [self nextResponder];
    while (responder != nil) {
        if ([responder isKindOfClass:[UIViewController class]]) {
            return (UIViewController *)responder;
        }
        responder = [responder nextResponder];
    }
    return nil;
}
@end

このマクロはカテゴリ汚染を回避します:

#define UIViewParentController(__view) ({ \
    UIResponder *__responder = __view; \
    while ([__responder isKindOfClass:[UIView class]]) \
        __responder = [__responder nextResponder]; \
    (UIViewController *)__responder; \
})

おすすめ記事