3

使用 Xcode 4.3.2 上的 Empty App 模板创建了一个项目,因此不涉及 NIB。

FooViewController.m

-(void) loadView {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor yellowColor];
    self.view = view;                     
}

因此,视图被实例化并分配给self.view. 两种方法:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"self.view is %@", self.view);
}

-(void) viewDidAppear:(BOOL)animated {
    NSLog(@"self.view is %@", self.view);
}

第一种方法会打印出来

self.view is <UIView: 0x18e4d0; frame = (0 0; 0 0); layer = <CALayer: 0x182a00>>

而第二个打印出来

self.view is <UIView: 0x18e4d0; frame = (0 20; 768 1004); layer = <CALayer: 0x182a00>>

所以在viewDidLoad和之间viewDidAppear,视图被调整大小。调整大小的机制是什么?我们真的可以指望它吗?因为即使是备受推崇的 Programming iOS, 2nd Ed 一书的作者 Matt Neuburg 也是这样做的(见第 508 页)。

4

4 回答 4

3

你必须了解 ViewController 的生命周期。在 viewDidLoad 中,将创建视图,但不会设置边界/尺寸。这将在接下来的步骤中发生。您可以使用 viewWillAppear 来设置尺寸(大多数人都会这样做)。ViewDidAppear 最后发生,您已经有了最终外观并且动画已经开始。

所以是的,在 viewDidLoad 和 viewDidAppear 之间,视图获得了它的维度和边界,它是完全可靠的,并且在 ViewController 文档中也有记录。

另请注意,每次需要创建视图时都会调用 viewDidLoad(例如第一次和在内存不足警告之后 - 通常在需要内存时释放视图),并且每次视图控制器位于顶部时都会调用 viewWillAppear堆栈及其视图即将被渲染。

查看与视图外观相关的文档:http: //developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDisplay-Notifications/RespondingtoDisplay-Notifications.html#//apple_ref/doc/uid/TP40007457- CH12

于 2012-05-24T20:42:04.810 回答
0

默认情况下,该autoresizesSubviews属性将导致视图在显示时调整其子视图的大小。

于 2012-05-24T20:21:09.023 回答
0

当您将此设为of时,看起来'viewController sview已调整大小。否则你必须手动设置它的框架。viewControllerrootViewControllerapplicationwindow

我试过这段代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];

    FooViewController *viewController = [[FooViewController alloc] init];

    self.window.rootViewController = viewController; 
    [self.window makeKeyAndVisible];

    FooViewController *viewController2 = [[FooViewController alloc] init];
    [viewController.view addSubview: [viewController2 view]];

    return YES;
}

viewController已调整大小,viewController2但没有。

另外:对于viewController所有这些方法都被调用:

viewDidLoad
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear

viewController2只为viewDidLoadviewDidAppear被调用。

也很有趣:viewController在它viewWillLayoutSubviews被调用之前被调整了大小。

编辑:

我认为这值得进一步测试。使用以下代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];

    FooViewController *viewController = [[FooViewController alloc] init];
    NSLog(@"after init: self.view is %@", viewController.view);
    self.window.rootViewController = viewController; 
    NSLog(@"after setting to rootViewController: self.view is %@", viewController.view);
    [self.window makeKeyAndVisible];
    NSLog(@"after makeKeyAndVisible: self.view is %@", viewController.view);

    return YES;
}

结果是:

viewDidLoad:                         frame = (0 0; 0 0)
after init:                          frame = (0 0; 0 0)
after setting to rootViewController: frame = (0 0; 0 0)
after makeKeyAndVisible:             frame = (0 20; 320 460)
viewWillLayoutSubviews:              frame = (0 20; 320 460)
viewDidLayoutSubviews:               frame = (0 20; 320 460)
viewDidAppear:                       frame = (0 20; 320 460)

[self.window makeKeyAndVisible];罪魁祸首也是如此。

于 2012-05-26T10:13:24.113 回答
0

self.view 直到它显示在屏幕上才真正创建。它是延迟加载的。调用后viewWillAppear,将设置框架。是的,您可以信任这些值,因为它们是根据手机的屏幕和方向设置的。

self.view 是一个比较特殊的视图,我经常不直接使用它,我通常只是添加一个容器子视图并将其作为主视图。由于调整大小,最好不要将 self.view 视为静态实体。确保正确设置子视图的自动调整大小掩码,以便在 self.view 更改时正确显示它们。

为了进一步回答您的问题,UIKit 专门设置视图的框架以考虑屏幕的大小、方向、导航栏、状态栏、工具栏等。您不能保证在viewWillAppear调用之前设置的框架将是相同。事实上,如果导航栏、方向或其他因素发生变化,self.view 会发生更大的变化。因此,即使viewWillDisplay您不能保证 self.view 的静态大小并且如果您更改它,它也会被适当地重置以反映设备的该状态。

UIKit 为我们处理了这个实现细节,这是一种奢侈,因为这样我们就不必考虑特定于设备的更改,只需确保正确设置了子视图的自动调整大小,而 UIKit 会处理其余的事情。

于 2012-05-24T20:39:55.757 回答