nib 中的 UIView 在 iPad 上是 nil,在 iPhone 上不是 nil

Posted

技术标签:

【中文标题】nib 中的 UIView 在 iPad 上是 nil,在 iPhone 上不是 nil【英文标题】:UIView in nib is nil on iPad, and not nil on iPhone 【发布时间】:2013-02-20 22:13:38 【问题描述】:

我的应用有一个奇怪的问题。我在运行时使用名为“LoginViewController”的 NIB 加载 VC。该NIB 有一堆UIView 对象的出口,这些对象放置在NIB 中,如下所示:

在运行时,我将这些 UIView 对象作为标题动态放置在我的表格视图中。在这种情况下,每个单独的UIView(除了右侧的UITableView 除外)都设置为像这样的IBOutlet。当然,每个都有不同的名称:

@property (strong, nonatomic) IBOutlet UIView *connectionInProgressView;

现在,在我的 VC 的 viewDidLoad 方法中,我运行了所有这四个单独的视图,并通过写入日志来确保它们存在:

NSLog(@"connection in progress view: %@", self.connectionInProgressView);

我的问题是:self.connectionInProgressView 在 iPad 上是 nil 而在 iPhone 上不是 nil。无论平台如何,所有其他视图都不是 nil 并且被实例化。我在 ios 5.0、5.1 和 6.1 的模拟器中运行它。我可以在所有 iPad 模拟器上重现该问题。我的应用程序运行良好,并在 iPhone 上使用微调器加载视图,但在 iPad 上它无法加载该视图,因为它是零!为什么!?

我尝试了以下方法:

检查我的 NIB 的文件所有者是否指向正确的视图 self.connectionInProgressView 不指向任何其他 IBOutlet 检查所有其他子视图是否以与违规视图相同的方式连接。他们是。 删除 self.connectionInProgressView 并在删除其所有 NIB 连接后重新创建它。 从视图中删除活动指示器并仅加载内部带有UILabel 的视图。不走运,它不是活动指示器。 检查了 VC 中可能引用self.connectionInProgressView 的任何代码。没有(除了viewDidUnLoad 中的 nil 声明)。 检查UINavigationControllerLoginViewController 的AppDelegate 属性的属性类型。 在 AppDelegate 上保留 LoginViewController 的副本,尽管这似乎很浪费,并且对结果没有任何影响。

[编辑 2]

问题:VC是如何加载的

我有一个UINavigationController,它是我的 AppDelegate 上的一个属性。 UINavigationController 是在 applicationDidFinishLaunchingWithOptions 中分配初始化的,我将我的 VC 作为根视图控制器传递给它。此时我将 VC 实例化。

// Create login/start up views
LoginViewController *loginViewController = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];

self.loginViewNavigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController];

if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
    self.loginViewNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;

请注意,这在 iPhone 上有效,尽管我稍后会在 iPad 上将此 UINavigationController 显示为模式表单(不确定这是否会导致我的问题)。

稍后在 AppDelegate 中,当一个不同的委托类抛出一个事件时,我将展示这个 UINavigationController,我的 VC 以模态方式包含在其中。我是这样做的:

if (self.loginViewNavigationController != nil) 

    [self.window.rootViewController presentViewController:self.loginViewNavigationController animated:YES completion:nil];

我正在发疯,试图确定为什么这个特定视图拖到我的 NIB 上并与所有其他视图一样连接起来,在 iPad 上是 nil 而在 iPhone 上不是 nil。

[编辑 1] 在搜索重复的问题时,我没有找到这个:

A few IBOutlets pointing to nil

我并不孤单!

有什么想法吗?

【问题讨论】:

您对 iPhone 和 iPad 有单独的目标吗?如果是这样,这个笔尖是否针对两者?您是否仅使用此笔尖遇到此问题(不在 iPad 上工作)?还是在所有笔尖上都有? 不,我正在构建一个通用二进制文件。 NIB 只针对一个目标。我只是在这个特定的 NIB 上遇到了这个问题。 viewDidUnload 永远不会被调用。摆脱它。 请显示实际导致 nib 加载的代码 - 它只是一些 UIViewController 的实例化吗? 【参考方案1】:

在构建通用应用程序时,您确定没有为 iPhone 和 iPad 创建单独的 NIB(通常为LoginViewController.xibLoginViewController~ipad.xib)?

或者您可能认为您只有一个 XIB,但在某些时候您有一个专用于 iPad 的 XIB,它被编译成一个 NIB,即使您在项目中删除了 XIB 文件,编译后的 iPad 专用 XIB 仍然存在构建产品。

无论如何,请尝试:

清理您的项目,甚至更好地清理您的构建产品目录 要执行后者,您可以删除派生数据文件夹(“组织器”窗口 -> “项目”选项卡 -> 在左侧选择您的项目 -> 单击“派生数据”旁边的“删除”按钮) 从所有模拟器中删除您的应用,以确保安全 再次构建并运行

如果这不起作用,一些想法可以帮助您调试并确定问题是否与使用不同 XIB 的 iPad 有关:

您可以尝试一些测试,例如修改您的 XIB 的另一个 IBOutlet,例如将不是 nil 的其他 IBOutlet 之一从它在 XIB 中连接到的视图中断开,这样当您运行您的应用程序再次应该记录为nil。如果在 iPhone 模拟器上是 nil(正如预期的那样,你刚刚断开了它)......但在 iPad 模拟器上仍然不是nil,那么这肯定意味着你为 iPhone 和 iPad 使用了不同的 XIB 文件。 您还可以在 XIB 中更改您的 UIView 的颜色,该颜色已正确连接到您的 IBOutlet 之一,并查看更改是否反映在 iPhone 和 iPad 或仅在 iPhone 上,所以检查您正在编辑的这个 XIB 是否与 iPad 中使用的相同。

【讨论】:

阿里 - 我会仔细阅读你的建议。为了回答你的第一个问题,我有一个完全独立的表格单元格大小问题,我认为我可以通过连接 ~ipad.xib 来解决。我试过了,它没有用,然后我删除了~ipad.xib。从那以后,我已经多次清理了这个项目,但都无济于事。 您是否也重置了模拟器? @Rog - 重置模拟器是什么意思。我对 iOS 开发还比较陌生,所以我可能会遗漏一些明显的东西。 @Ali - 上面的步骤 1-3 解决了我的问题。我删除了构建产品目录,从每个模拟器中删除了应用程序,瞧,幽灵 .xib 问题已解决。 干得好。这吸引了很多人,包括有经验的 Xcode 用户:构建应用程序不会从以前的构建中删除应用程序中的内容,所以你真的不知道里面有什么。唯一的出路是清理一切。在这里比较我的答案:***.com/a/6247073/341994【参考方案2】:

我遇到了类似的问题,清理了我的项目,删除了派生数据,确保我没有为 iPad 使用单独的 xib;似乎没有任何效果。原来我的问题非常简单。我像这样初始化我的视图控制器:

// In Swift
let vc = MyViewController()

而不是直接使用 nibName:

let vc = MyViewController(nibName: "MyViewController", bundle: NSBundle.mainBundle())

由于我的 nil-outlet 错误似乎只在 iPad 上测试时出现,所以我从未想过要检查控制器是如何初始化的。

【讨论】:

【参考方案3】:

对于这个特定的案例,我遇到了一件奇怪的事情。我让UITextField 成为viewDidLoad 的第一响应者,我让NSNotifications 连接到UITextField 来管理键盘框架等。但有趣的是,当通知在viewDidLoad 中发送时,仅在iPad 上,网点为零(与 iPhone 不同)。很奇怪。

【讨论】:

以上是关于nib 中的 UIView 在 iPad 上是 nil,在 iPhone 上不是 nil的主要内容,如果未能解决你的问题,请参考以下文章

nib loader 只保留 nib 中的第一个*** UIView?

使用 nib 中的视图重新加载 UIView 属性

如何从 ViewController 中的 xib (nib) 实例化 UIView / UITableView

捆绑中的 NIB 缺少名称 MainWindow-iPad

制作一个 UIVIew,它出现在 xcode 项目中的所有 .NIb 文件上

如何在 nib 中为 UIView 应用自动布局?