3

我发现了一个奇怪的行为,并想解释一下我所做的断言是错误的。

在新创建的 WindowBased 项目的 AppDelegate 类中,我将 UIViewController 添加到窗口。
我可以通过两种不同的方式做到这一点:
- 使用 IBOutlet。在 IB 中,我只是实例化了一个 UIViewController,将其类设置为 TestViewController 并连接它(代码的场景 A)。
- 使用代码创建 UIViewController(场景 B)。

    - (void)applicationDidFinishLaunching:(UIApplication *)application {    

#define USE_IBOUTLET YES // Comment this line to switch to scenario B

#ifdef USE_IBOUTLET
    // Scenario A

    [window addSubview:theTestViewController.view];
    [window makeKeyAndVisible];
#endif


#ifndef USE_IBOUTLET
    // Scenario B

    TestViewController *theTestViewControllerProgrammatically;

    theTestViewControllerProgrammatically = [[TestViewController alloc] initWithNibName:nil bundle:nil];

    // According to Apple: "It is a good idea to set the view's frame before adding it to a window.", so let's do it
    [theTestViewControllerProgrammatically.view setFrame:[[UIScreen mainScreen] applicationFrame]];

    [window addSubview:theTestViewControllerProgrammatically.view];

    [window makeKeyAndVisible];
#endif
}

由于我没有在 IB 中对对象进行任何自定义,因此在这两种情况下我应该具有相同的行为。

方案 A,使用 IBOutlet 按预期工作。
但是场景 B 存在以下问题:
- 视图不在正确的位置(高 20 像素,并且被状态栏覆盖)。
- 视图没有正确调整大小(例如,尝试切换通话状态栏)

为什么?

如果您想重现问题,请在此处压缩项目存档:http: //dl.dropbox.com/u/1899122/code/ProtoWindowBasedStrangeness.zip

4

3 回答 3

2

在我冗长的回答之后,这听起来真的很愚蠢,但是您遇到的问题很容易解决(以编程方式)。

这一行:

[theTestViewController.view setFrame:[[UIScreen mainScreen] applicationFrame]];

实际上应该是:

[theTestViewControllerProgrammaticaly setFrame:[[UIScreen mainScreen] applicationFrame]];

您正在为 IB 设置的 VC 设置框架,而不是您以编程方式创建的那个。

无论如何 - 值得注意的是,我所有的评论仍然适用!如果您不使用 IB 的控制器对象(例如,设置导航栏项目),您仍然需要以编程方式执行一些操作

保罗

于 2010-02-18T20:17:25.447 回答
1

我遇到了一个与您非常相似的问题,因为我注意到 VC 对象并非都是平等的!我遇到的问题是设置导航栏项目,当文件所有者是我以编程方式实例化的视图控制器对象时,我似乎无法做到这一点。它仅在我取消归档 IB 的控制器对象时才有效。

我下载了你的项目并玩了一下,这让我对可能发生的事情有了更多的思考。我想我可以提供一个合理的答案,但不确定是否有一个简单的解决方案......

我相信正在发生的事情是,Apple 在 IB 中创建了这些稍微更专业的控制器对象。这可能是真的一个建议是 IB VC 对象有一个你可以设置的属性,它没有我可以看到的 UIViewController 类的直接对应属性,所以 IB 的控制器对象可能具有非 IB UIViewController 子类不能的一些附加功能利用。鉴于 .xib 中的对象是完整的“冻干”对象,Apple 可能已经包含了我们在它们的 IB 版本中看不到或使用的各种私有属性——这可能会对对象的初始化方式产生一些影响.

例如,在您MainWindow.xib的 IB VC 对象中,您可以从 Inspector Palette 中设置属性,例如“Resize View From NIB”。如果您取消选中此选项并重新运行您的应用程序,您将看到 VC 与场景 B 中的显示完全相同。因为您无法从 File's Owner 属性中检查此项目(即使它是 UIViewController ),您无法利用视图控制器所做的任何事情来为您提供所需的行为。

这样做的结果是,当您TestViewController.xib在代码中使用初始化 VC 对象时,没有设置 VC 的任何 IB 特定属性,因此创建了一个沼泽标准 UIViewController,因此诸如“Resize View From NIB”属性之类的东西并且设置导航项必须自己实现。

我还没有找到一种方法来利用 IB 的视图控制器在我实例化它们时所具有的功能initWithNibName:bundle:nibBundle(我猜这都是我们无法访问的私有内容),但希望这可能会给你一个起点...

当然,我可能完全错了,有人会让我看起来像个白痴!

保罗

于 2010-02-14T19:35:27.533 回答
0

可能在 B 的情况下,该视图不知道状态栏的存在。您需要相应地调整它的大小并调整其位置以考虑状态栏。这是通过更改 UIView 的框架(大小)和边界(位置)属性来完成的。

于 2010-02-13T12:50:11.720 回答