在 iPad 端口中管理视图控制器
Posted
技术标签:
【中文标题】在 iPad 端口中管理视图控制器【英文标题】:Managing View Controllers in iPad port 【发布时间】:2010-10-28 14:28:52 【问题描述】:我有一个为 iPhone 开发的应用,但现在想移植到 iPad。 iPhone 应用程序是导航风格的,并且基于由导航控制器管理的离散表视图控制器。 iPad 更大的屏幕空间意味着我可以轻松地将几个这样的表格视图控制器同时安装到屏幕上。
问题是如何?我应该
a) 让主视图从单独的 NIB 加载两个表视图控制器,然后将它们定位在屏幕上(我不确定如何设置从 nib 加载的子视图的 x 和 y)。
b) 在我的主 nib 中创建子视图,并用我现有的类中的数据填充这些视图(如果是这样,我如何连接 IBOutlets)?
c) 做一些完全不同的事情
我应该指出的一点是我不想使用分屏选项。
【问题讨论】:
这个问题相当令人困惑,但您应该保留 Apple HIG 及其创建原因。 Apple 产品中 UI 的一致性使 ios 应用程序生态系统易于为其客户采用。如果您创建的 UI 与用户对 Apple 产品功能的期望不一致,则可能会对您的应用程序的感知产生负面影响 对不起,如果我没有说清楚。从 HIG 的角度来看,我并不想做任何违反直觉的事情,只是 iPad 为创建独特的用户界面打开了更多的空间。 【参考方案1】:警告!此 QA 现在仅具有历史价值。
现在在 iOS 中用容器视图做这种事情是微不足道的,这就是 Apple 编辑它们的原因:
https://***.com/a/25910881/294884
How to add a subview that has its own UIViewController in Objective-C?
历史答案...
".. 我如何设置从 nib 加载的子视图的 x 和 y?"
我不确定我是否完全理解菲尔的问题,但这里有一个简单明了的方法:
启动界面构建器并在新的更大的 iPad 视图中,只需添加新的更小的视图 (UIViews)... 将它们准确放置在您想要的位置和方式。我们将把这些称为“篮子”视图。
假设您在其他应用中的一个复杂视图是您的 fatDogs 视图。调用新的篮子视图 fatDogsBasket。然后在代码中,在 viewDidLoad 中,对所有这些“篮子”执行以下操作...
[fatDogsBasket addSubview:fatDogs.view];
[clientsBasket addSubview:clients.view];
[namesBasket addSubview:names.view];
[flashingLightsBasket addSubview:flashingLights.view];
// etc
你已经完成了! (显然,确保相关的视图控制器、fatDogs、flashingLights 等都准备就绪并实例化。)
“篮子”系统很方便,因为每个系统都将您以前的工作放在一个地方;有用的是,您可以(比如说)通过触摸篮子来设置整体隐身或其他任何东西。显然,如果你想在代码中设置或者移动篮子的位置,就去吧
happyBasket.frame = CGRectMake(509,413,
happyBasket.frame.size.width,
happyBasket.frame.size.height);
iOS 中的 UIView 非常轻量级,所以再添加一层 UIView 完全没有问题。
我希望这就是你的意思!
--------稍后...
你接着问:“只是为了确保我清楚实现这一点的正确方法。主视图控制器为每个'篮子'都有 IBOutlet,它的这个 IBOutlet 连接到我的子视图'我正在调用。我将在每个篮子中显示的每个视图控制器都有自己的 nib 和关联的 IBOutlets。对吗?--"
所以,“主视图控制器为每个'篮子'都有 IBOutlets”...
没错,新应用中的主视图,在 .h 文件中会有这样的行:
IBOutlet UIView *fatDogsBasket;
请注意,您只是将“fastDogsBasket”声明为 UIView。你不应该太担心“IBOutlet”这个词。这意味着“我需要能够在界面控制器中查找此项目。”重要的是要意识到它什么都不做。
所以是的,所有的“篮子”都将是 UIView,因此您当然必须在主视图控制器的 .h 文件中将它们删除。个人不会使用“视图控制器具有 IBOutlets”这一短语。它有点混淆事物并给出错误的想法。只需说“不要忘记在头文件中将 UIViews 标记为 iboutlets。”
所以无论如何,这正是你所做的,在主控制器的 .h 文件中声明所有“篮子”UIView,并确实将它们全部标记为 IBOutlets,以便界面构建器更容易工作。接下来..
“它的这个 IBOutlet 连接到我正在调用的子视图”——这是错误的。
像 fatDogsBasket 这样的篮子只是一个 UIVIEW,就是这样。它只是一个 UIView。
现在,如您所知,您可以将 UIViews 放入其他 UIViews。 (显然,这是司空见惯的,每个 UIView 里面都有很多 UIViews 等等 - 这是构建界面的最基本部分。)
那么,您打算在 fatDogsBasket uiview 中放入什么?你将把你以前的所有工作都放在 fatDogs 上!以前(针对 iFone)您编写了一个很棒的类 - 一个视图控制器 - 称为 fatDogs。 (它甚至可能有很多子类等等。)
我们现在要从 fatDogs(当然,就是 fatDogs.view)中获取视图,并将其放入 fatDogsBasket 中。 (回想一下 fatDogsBasket 是一个 UIView。)
所以首先你必须将你惊人的类 fatDogs(来自旧项目)完全包含在你的新项目中。单击“添加现有的苍蝇/类”或类似的东西......你会弄明白的。是的,添加所有的类文件、xib、任何子类等等。
然后,只需执行此操作 .. 在您新的超级强大的超级控制器中,在 viewDidLoad 中,对所有“篮子”执行以下操作...
[fatDogsBasket addSubview:fatDogs.view];
[clientsBasket addSubview:clients.view];
[namesBasket addSubview:names.view];
[flashingLightsBasket addSubview:flashingLights.view];
// etc
你已经完成了!请注意,来自 fatDogs 的视图(即 fatDogs.view)现在显示在 UIView fatDogsBasket 内。 fatDogs 类现在将完全正常工作,就像过去一样!令人难以置信的是,您可以轻松地(在您的新控制器中)执行诸如简单地移动 fatDogsBasket 之类的操作,并且它会同时轻松地移动 fatDogs 视图,而无需担心 fatDogs 及其视图的细节。
你终于问了..
“我将在每个篮子中展示的每个视图控制器都有自己的 nib 和关联的 IBOutlets。”
完全正确。当您将旧系统“fatDogs”添加到新项目时,您将添加它的所有 xib 文件等等。在这些类中发生或未发生的任何事情,可能与按钮或任何其他标记为 iboutlets 或其他任何东西有关,在这些类中仍然是相同的。我敢肯定,当您在新项目中使用这些旧类时,什么都不会改变。
只是为了记录..“我将在每个篮子中显示的每个视图控制器..”准确地说,您并没有真正显示为这样的视图控制器,您显示的是视图控制器(!!)。换句话说,对于 fatDogs(一个视图控制器),您将显示它的视图,简单地说,就是 fatDogs.view。 (当然,“view”是任何 UIViewController 的属性,所以你可以说 vcName.view 就完成了。)
希望对你有帮助!
最后你问..................................................
“我已经编译好了,但是我的篮子显示为空,即它们没有显示我导入的视图控制器的视图。”
Tell 是旧项目中您的 UIViewController 类之一的名称,因此我们可以具体说明
假设您有一个名为 HappyThing 的旧 UIViewController。所以你很可能会有一个文件 HappyThing.h 和一个文件 HappyThing.m 和一个文件 HappyThing.xib。
将所有这些都放在新项目中,您必须使用 Add->Existing Files 这样做。 (在 XCode 左侧的列表中控制您当前的文件名之一。)
您必须在新项目的某个地方或其他地方执行此 #import "HappyThing.h" - 无论是在 Prefix.pch 文件中还是在新 UIControllerView 的顶部
要清楚,在 HappyThing.h 中,您将有一行代码 @interface HappyThing : UIViewController
在您的新 UIViewController.h 文件中,您必须添加一个新变量,我们将其命名为 xxx,
HappyThing *xxx;
请注意,xxx 的类型是 HappyThing。 (请注意,作为一项规则,您将使用命名约定“happyThing”(注意小写“h”)而不是“xxx”,但它只是一个变量,我希望您清楚它只是一个变量。 )
接下来!目前它只是一个没有指向任何东西的变量,它什么都不是。 (就好像你说“int x”,但实际上并没有说“x = 3”或其他什么。)所以!在您的代码中,您必须实际实例化 xxx。
xxx = [[HappyThing alloc] init]; [xxxBasket addSubview:xxx.view];
请注意,第一行是使 HappyThing 实例存在的原因。当然,您想使用“xxx”来指向该实例。
第二行将视图放入相关的篮子!请注意,您当然想要的是与 xxx 相关联的视图(即 xxx.view)……请记住,xxx 是 UIViewController,它本身并不是 UIView。关联的 UIView 是“xxx.view”。 (视图实际上只是 xxx 的一个属性。)
-
内存管理!请注意,您使用“alloc”来使 xxx 存在。这意味着您确实拥有它,当然这意味着您不需要在那里发送保留。此外,由于您确实拥有它,这意味着您最终必须释放它。 (easy ... [xxx release];)
所以只需添加行 [xxx release];到新 UIViewController 中的 dealloc 例程。 (如果您忘记执行此操作确实不会造成任何伤害,但无论如何都要执行此操作。)可以想象,一旦您对该过程更加满意,您可能会出于某种原因希望提前发布它。
(我只是在做一个包含大量大表、弹出框等的项目,所以我只是在运行中制作它们并尽快摆脱它们,以使用更少的内存。但是所有的在这个阶段与你无关。)
所以现在你应该在屏幕上看到它了!
不要忘记,如果您之前在 HappyThing 中有一些例程,您必须调用它才能开始它的工作(可能是“beginProcessing”或其他什么),您必须自己从新的 UIViewController 调用它。因此可能是这样的:
xxx = [[HappyThing alloc] init];
[xxxBasket addSubview:xxx.view];
[xxx beginProcessing];
[xxx showAmazingRedFlashingLights]; // or whatever
你终于问了……
“当您使用这种技术时,您是简单地将导入文件的标题包含在您的主视图控制器中,还是以某种方式转发它们?”
这不是你的问题,你的问题是你没有用 xxx = [[HappyThing alloc] init]; 行实例化它。所以,祝你好运!
关于代码行“@class HapyyThing”,如果您只想将它放在新 UIControllerView 定义的开头上方。通常,如果您将包含行放在最佳位置,则不必这样做。无论如何,这是一个不相关的问题。如果您的新 UIViewController 找不到 HappyThing,它根本无法编译。享受吧!
【讨论】:
谢谢。我猜想一定有这样的解决方案,但我一直在努力弄清楚如何实现它。 只是为了确保我清楚实现这一点的正确方法。主视图控制器具有每个“篮子”的 IBOutlet 及其与我正在调用的子视图的此 IBOutlet 连接。我将在每个篮子中展示的每个视图控制器都有自己的 nib 和关联的 IBOutlets。对吗? 嗨,乔,感谢您的出色回答。我的问题可能不是很清楚,但你明白我在说什么。我已经编译好了,但是我的篮子显示为空,即它们没有显示我导入的视图控制器的视图。当您使用这种技术时,您是简单地将导入文件的标题包含在您的主视图控制器中,还是以某种方式转发它们? 乔,再次感谢。你说得对,我没有实例化它。以上是关于在 iPad 端口中管理视图控制器的主要内容,如果未能解决你的问题,请参考以下文章