基于视图的 iOS 应用程序模板

发布于 2024-10-01 23:39:03 字数 806 浏览 0 评论 0原文

我读过 Apple 的“你的第一个 iOS 应用程序”指南,其中的所有内容对我来说似乎都一目了然。然而,当我尝试了解 XCode 中提供的基于视图的 iOS 应用程序模板如何工作时,我遇到了一些有趣的难题。

据我了解,应用程序从 *-Info.plist 文件获取主 nib 文件名(通常为 MainWindow.xib)。我不明白的是,XCode 如何知道哪个 nib 文件与默认使用此基于视图的应用程序模板创建的控制器关联。在指南中,您从基于 Window 的应用程序开始,并且您“必须编写”类似以下内容:

MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

[self setMyViewController:aViewController];

这非常有意义。然而,事实证明,在基于视图的 iOS 应用程序模板中,没有这样的东西,而且这个 nib 规范实际上并不是首先需要的,只要您使用选项“使用 XIB 作为用户界面”创建 UIViewController 子类即可”检查过。我的问题是,XCode 如何知道哪个 nib 与该控制器关联,即它是否将此连接存储在某些文件中,或者可能通过某种约定(控制器和 nib 文件的名称可能相同)?此外,MainWindow.xib 中界面构建器的控制器视图中的“从“MyViewBasedAppController”加载”副标题来自哪里?当我手动添加控制器时它肯定不存在,所以我很好奇 XCode 在我背后做了什么魔法,当我认为我只是选择一个简单的代码模板时。

I've read Apple's "Your first iOS application" guide and everything there seems crystal clear to me. However, when I try to understand how View-based iOS application template provided in XCode works, I run into some interesting conundrums.

I understand that the application gets the main nib file name (usually, the MainWindow.xib) form the *-Info.plist file. What I do not understand is, how does the XCode know which nib file is associated with the controller that is created with this View-based application template by default. In the guide, you start with the Window-based application, and you "have to write" something like:

MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

[self setMyViewController:aViewController];

which makes perfect sense. However, it turns out that in the View-based iOS application template there is no such thing, and that this nib specification was not actually needed in the first place, as long as you created your UIViewController subclass with option "With XIB for user interface" checked. My question is, how does XCode know which nib is associated with this controller, i.e. is it storing this connection in some of the files, or maybe by some sort of convention (same name for controller and nib file, perhaps)? Moreover, where does that 'Loaded from "MyViewBasedAppController"' subtitle come from in Interface builder's view of controller within MainWindow.xib? It's definitely not there when I add the controller by hand, so I'm curious to what magic does XCode do behind my back, when I think I'm just selecting a simple code template.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

执笔绘流年 2024-10-08 23:39:03

如果您查看目标信息(双击目标将其调出),“属性”选项卡您将看到主 Nib 文件的名称。出于这些目的,“Nib”和“Xib”这两个词可以互换; Xib 只是 Nib 的更新替代品。

它将是模板中的“MainWindow”。如果您打开 MainWindow.xib,您将看到其中有一个名为“[项目名称] App Delegate”的对象,如果您显示检查器并在“i”选项卡下进行检查,您将看到该类的类型命名在顶部。如果您检查连接选项卡(向右箭头),您将看到文件所有者(即 UIApplication 本身)附加了其“委托”属性。

您还会看到它有一个名为“viewController”的插座。它附加到 xib 中名为“[项目名称]视图控制器”的另一个对象。检查它的类型,您将看到它是 Xcode 添加到您的项目中的视图控制器的类型。查看其属性(检查器中的第一个选项卡,带有滑块图形),您还会看到指定了一个单独的 nib 文件来包含其主要详细信息。

为了便于论证,假设我将我的项目命名为“NibTest”并且没有进行任何更改。

在运行时,设备加载 Info.plist。在那里它看到委托的类型为 NibTestAppDelegate。因此它将实例化 NibTestAppDelegate 类的实例并将 UIApplication 的委托属性设置为其。

然后它会从 MainWindow.nib 中看到 NibTestAppDelegate 有一个名为 viewController 的 NibTestViewController 类型的成员。因此它将创建一个实例,并在刚刚创建的 NibTestAppDelegate 实例上设置 viewController 属性。

在此过程中,它将打开另一个 xib 并继续执行相同的步骤。

Objective-C 具有完全反射的运行时,因此您可以在运行时通过类名实例化对象。例如,这是 Objective-C 和 C++ 之间的区别之一。

Xcode 不会生成任何隐藏代码或依赖任何隐藏命名约定。整个事情是由操作系统在运行时计算出来的。

编辑:例如,代替您的示例:

    MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

您实际上可以这样做:

    MyViewController *aViewController = [[NSClassFromString(@"MyViewController") alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

只要 MyViewController 存在于程序中或更广泛的运行时中,它们就会以相同的方式运行。

您也可以将任何其他您喜欢的字符串对象传递给 NSClassFromString。如果您愿意的话,甚至可以向用户询问(尽管出于安全原因这不是一个好主意)。

If you look in the target info (double click on the target to bring that up), 'Properties' tab you'll see the name of the main Nib file. The words 'Nib' and 'Xib' are interchangeable for these purposes; Xib is just a newer alternative for Nib.

It'll be 'MainWindow' fresh from the template. If you open MainWindow.xib you'll see that in there is an object called '[project name] App Delegate', and if you show the inspector and check under the 'i' tab you'll see the type of class that is named at the top. If you check the connections tab (the right facing arrow), you'll see that the File Owner (which is the UIApplication itself) has its 'delegate' property attached.

You'll also see that it has an outlet called 'viewController'. That's attached to another object in the xib called '[project name] View Controller'. Check the type on that and you'll see it's the type of view controller that Xcode has added to your project. Looking at its attributes (the first tab in the inspector, with the slider graphic), you'll also see that a separate nib file is specified as containing its main details.

For argument's sake, suppose I called my project 'NibTest' and made no changes.

At runtime, the device loads Info.plist. In there it sees that the delegate is of type NibTestAppDelegate. So it'll instantiate an instance of the class NibTestAppDelegate and set the UIApplication's delegate property to it.

It'll then see from MainWindow.nib that NibTestAppDelegate has a member named viewController of type NibTestViewController. So it'll create an instance of that and set the viewController property on the NibTestAppDelegate instance it just created to it.

In doing that it'll open the other xib and continue doing the same sort of steps.

Objective-C has a fully reflective runtime, so you can instantiate objects by their class name at runtime. This is one of the differences between Objective-C and C++, for example.

Xcode isn't generating any hidden code or relying on any hidden naming conventions. The whole thing is figured out at runtime by the OS.

EDIT: for example, in place of your example:

    MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

You could actually do:

    MyViewController *aViewController = [[NSClassFromString(@"MyViewController") alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];

They'll operate identically as long as MyViewController exists in the program or in the wider runtime.

You could alternatively pass any other string object you like to NSClassFromString. Even ask the user for it if you want (though it'd be a really bad idea for security reasons).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文