Cocoa-Touch内部:视图如何知道其控制器?

时间:2011-04-12 18:45:50

标签: objective-c cocoa-touch ios

如果您向视图添加子视图或向窗口添加视图,iOS如何知道此视图所属的控制器?

简单示例: 拥有一个没有UIViewController的UIView并将其添加到窗口[window addSubView:myView] - >它不会旋转。 现在使用UIViewController,让它实现shouldAutoRotateToInterfaceOrientation:并将控制器的视图添加到窗口:[window addSubView:myController.view] - > 神奇地,视图将调整为界面方向。

但请查看代码:在这两种情况下都添加了UIView。 iOS如何可能意识到在第二种情况下涉及UIViewController

我对如何在内部完成这项工作感兴趣。我最好的猜测是UIViewController.view是一个setter,它将控制器添加到内部控制器数组中,或者将自己分配给一个保存当前活动控制器的内部变量。

3 个答案:

答案 0 :(得分:4)

简单。查看UIView.h。它就在那里。每个UIView都有一个指向UIViewController的指针(显然称为“viewDelegate”)。

答案 1 :(得分:1)

Dave DeLong是正确的(获得+1),因为它明确地将UIView.h定义为@package,因此UIKit中的任何内容都可以访问它。

以下是仅出于教育目的访问该变量的示例(显然,您不会在实际应用程序中执行此操作)。

<强> SomeAppDelegate.m

@synthesize navigationController=_navigationController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    // Add the navigation controller's view to the window and display.
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];

    //DO NOT TRY THIS AT HOME
    UIView *mynavview = self.navigationController.view;
    //Guaranteed _viewDelegate atleast in iOS 4.3
    Ivar ivar = class_getInstanceVariable([UIView class], "_viewDelegate");
    UIViewController *controller = object_getIvar(mynavview, ivar);
    NSLog(@"controller = self.navigationController? %@", controller == self.navigationController ? @"Yes" : @"No");

    return YES;
}

答案 2 :(得分:0)

UIViewController有一个私有类方法(我相信称为controllerForView:),用于查找视图的控制器。在内部,可能有一个表用于将两者连接在一起,此方法只是在该表中找到正确的位置并返回其值。当结果为nil时,将使用默认实现(不要旋转)。

如果要确定方法的名称,请在-[UIView becomeFirstResponder]中设置断点,点击文本字段,然后逐步执行代码,直到它出现在调用堆栈中。我建议使用becomeFirstResponder因为它比获取视图控制器的大多数事情更容易控制。