我很想看到有关如何以编程方式管理视图的详细说明。我将概述我现在是如何做的,并希望评论我的方法如何糟糕,或只是概述如何干净利落地完成它。
基本上,在我的应用程序的主视图控制器的loadView
方法中,我首先创建一个根视图并为其设置self.view
。当我想要附加一个控制器时,比如显示的第一个控制器,我称之为:
-(void) attachViewForController:(UIViewController*)controller
{
[self.mRootView addSubview:controller.view];
[controller viewWillAppear:NO];
}
请注意,我明确地调用了viewWillAppear
(我相信它并没有自动调用它),我手动执行任何动画来引入视图(滑入,淡入等)。这种方法在这里有什么不对或有什么不对吗?
现在,当我想离开此视图并切换到另一个视图时,我调用一个方法来设置开关:
-(void) setControllerSwitch:(UIViewController*)outgoingController
incomingController:(UIViewController*)incomingController
delay:(float)delay;
{
self.mOutgoingController = outgoingController;
self.mIncomingController = incomingController;
self.mSwitchControllerTimer = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(switchControllerCallback) userInfo:nil repeats:NO];
}
此时,我已经开始为传出视图退出动画,并且此方法记录控制器并调度一个方法,该方法将在传出视图完成动画时执行实际切换。像这样:
-(void) switchControllerCallback
{
self.mSwitchControllerTimer = nil;
// remove outgoing view
[mOutgoingController.view removeFromSuperview];
// add incoming view
[self attachViewForController:mIncomingController];
}
这是管理事物的好方法吗?几点:
我知道我可能会设置一个回调来在传出控制器动画结束时触发,但是选择通过显式延迟参数执行此操作以留出空间以允许我跨越淡入淡出视图。但是,我认为提前调用setControllerSwitch
实际上可能不允许交叉淡化,因为它会提前破坏旧控制器并使其切断其动画。
如前所述,我很想知道明确调用viewWillAppear
是否是否定,并且有更合适的方法来管理视图流。
答案 0 :(得分:1)
从Apple开发人员文档中复制,但对于了解视图和管理多个视图有很大帮助。
有效使用视图的提示
自定义视图对于您需要绘制标准系统视图未提供的内容的情况非常有用,但您有责任确保视图的性能足够好。 UIKit尽其所能优化与视图相关的行为,并帮助您在自定义视图中实现良好的性能。但是,您可以通过考虑以下提示来帮助UIKit。
视图并不总是具有相应的视图控制器
应用程序中的各个视图和视图控制器之间很少存在一对一的关系。视图控制器的工作是管理视图层次结构,该层次结构通常由用于实现某些自包含功能的多个视图组成。对于iPhone应用程序,每个视图层次结构通常会填满整个屏幕,但对于iPad应用程序,视图层次结构可能只填充屏幕的一部分。
在设计应用程序的用户界面时,重要的是要考虑视图控制器将扮演的角色。视图控制器提供了许多重要的行为,例如协调屏幕上的视图呈现,协调从屏幕上删除这些视图,释放内存以响应低内存警告,以及响应界面方向更改来旋转视图。绕过这些行为可能会导致您的应用程序行为不正确或以意想不到的方式行事。
有关查看控制器及其在应用程序中的角色的更多信息,请参阅适用于iOS的View Controller编程指南。
最小化自定义绘图
虽然有时需要自定义绘图,但也应尽可能避免使用。您应该真正执行任何自定义绘图的唯一时间是现有系统视图类不提供您需要的外观或功能。只要您可以使用现有视图的组合来组合内容,最好将这些视图对象组合到自定义视图层次结构中。
利用内容模式
内容模式可最大限度地缩短重绘视图所花费的时间。默认情况下,视图使用UIViewContentModeScaleToFill内容模式,该模式缩放视图的现有内容以适合视图的框架矩形。您可以根据需要更改此模式以不同方式调整内容,但如果可以,则应避免使用UIViewContentModeRedraw内容模式。无论哪种内容模式生效,您都可以通过调用setNeedsDisplay或setNeedsDisplayInRect来强制您的视图重绘其内容:。
尽可能将视图声明为不透明
UIKit使用每个视图的opaque属性来确定视图是否可以优化合成操作。对于自定义视图,将此属性的值设置为YES会告诉UIKit它不需要在视图后面呈现任何内容。较少的渲染可以提高绘图代码的性能,并且通常会受到鼓励。当然,如果将opaque属性设置为YES,则视图必须使用完全不透明的内容完全填充其边界矩形。
滚动时调整视图的绘图行为
滚动可以在很短的时间内产生大量的视图更新。如果您的视图的绘图代码未正确调整,则视图的滚动性能可能会很低。不要试图确保视图的内容始终保持原始状态,而是考虑在滚动操作开始时更改视图的行为。例如,您可以临时降低渲染内容的质量,或在滚动过程中更改内容模式。滚动停止后,您可以将视图返回到先前的状态,并根据需要更新内容。
不要通过嵌入子视图来自定义控件
虽然技术上可以将子视图添加到标准系统控件 - 从UIControl继承的对象 - 但是您永远不应该以这种方式自定义它们。支持自定义的控件通过控件类本身中明确且记录良好的接口来实现。例如,UIButton类包含用于设置按钮的标题和背景图像的方法。使用定义的自定义点意味着您的代码将始终正常工作。通过在按钮内部嵌入自定义图像视图或标签来绕过这些方法,可能会导致应用程序现在或在将来的某个时刻出现错误,如果按钮的实现发生更改。