iOS5如何“偷懒”初始化标签栏的控制器?
我有一个 TabBar 控制器,最多有 9 个控制器,每个控制器都有一个导航控制器。目前,我在应用程序委托中分配并初始化它们中的每一个,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{...}
这使得我的应用程序在第一次启动时需要相当长的时间才能启动。我想通过延迟初始化来减少初始加载时间。
当第一次为选项卡栏选择视图控制器时,有没有办法“延迟”初始化视图控制器?
研究 iOS5 的情节提要可以帮助我解决这个问题吗?
谢谢你!
I have a TabBar controller with up to 9 controllers, each one has a navigation controller. Currently, I alloc and init each one of them within the app delegate in the
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{...}
This makes my app take quite some time to start when first started. I'd like to reduce the initial loading time with lazy initialization.
Is there a way to "lazily" init view controllers when they are first selected for the tab bar?
Will looking into storyboards for iOS5 help me with this issue?
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
将控制器定义为惰性控制器怎么样?
我的意思是,如果应用程序由于九个视图控制器的初始化而需要一些时间来启动,那么这与控制器在初始化时实际执行的操作有关。因此,您可以通过两个步骤使控制器延迟初始化:一,当您将所有控制器添加到选项卡栏控制器时;二,当您将所有控制器添加到选项卡栏控制器时;第二,当您选择特定选项卡时,相应的控制器将被初始化。
我认为这是最干净的方法。
否则,我敢打赌直接使用
UITabBar
在您自己的选项卡栏控制器类中管理它。作为最后一个选择,我将尝试根据某些逻辑在适当的时间调用
setViewControllers:animated:
来动态更改选项卡栏控制器的内容。例如,您可以在application:didFinishLaunchingWithOptions:
中仅使用 5 个视图控制器初始化选项卡栏控制器,然后稍后添加其余部分...但我的实际建议是让组件控制器变得懒惰。 ..
编辑:在阅读评论中的问题后...
如果您尝试延迟初始化控制器,我的意思如下:
您将初始化控制器(或者 UIKit 将在加载笔尖时初始化)通过调用 [[...分配]初始化...];这不会改变;
init
方法会将控制器初始化为其默认状态,例如设置属性和 ivar 值,并且不会执行任何更复杂的操作;在控制器视图显示之前,通过调用特定的方法完成其初始化;这将完成“相当多的委托”部分,我认为这是初始化的冗长部分。
很抱歉,如果谈论“延迟初始化”导致组件的逻辑初始化和
init
方法的内容之间出现歧义。对于第 3 点,您有多种选择来完成初始化。
可能性是当控制器即将显示时。在这种情况下,您可以在选项卡栏控制器委托中定义
-tabBarController:didSelectViewController:
,或者使用viewWillAppear
。这将为您提供最懒的初始化,但在视图出现之前选择选项卡的确切时刻可能会增加一些延迟。更好的是使用 viewDidLoad,它会给你一种不那么懒惰的初始化;您的所有控制器的初始化都会在您无法控制的某个时间点发生(当然,在显示视图之前),因此可能会稍微延迟一些,但不会在
applicationDidFinishLoading
并且会更加 UI 友好,因为它将由主循环控制。绝对是尝试的第一个选择。另请查看 UIViewController 参考。最后是关于单独线程的注释。请记住,从单独的线程使用
UIKit
并不都是安全的,所以要小心。What about defining your controllers as lazy controllers?
I mean, if the app takes some time to start due to initialization of nine view controllers, then this has to do with what the controller actually do at init time. So, you could make the controller lazily init in two steps: one, when you add all of your controllers to the tab bar controller; two, when you select a specific tab, then the corresponding controller gets initialized.
I think this is the cleanest approach.
Otherwise, I would bet on directly using
UITabBar
to manage it in your own tab bar controller class.As a last option, I would try and change on the fly the content of the tab bar controller by calling
setViewControllers:animated:
at appropriate times according to some logics. For example, you could initialize the tab bar controller with only 5 view controllers inapplication:didFinishLaunchingWithOptions:
, then add the rest at a later moment...But my actual suggestion is making the component controllers lazy...
EDIT: after reading your question in the comment...
if you would give a try to lazy initialization of your controllers, what I mean is following:
you will initialize your controllers (or UIKit will when loading the nib) by calling [[... alloc] init...]; this is not changing;
the
init
method will initialize the controller to its default state, like setting properties and ivar values, and do nothing more complex;before the controller view gets displayed, you complete its initialization by calling a specific method; this would carry through the "quite a lot of delegation" part, which I assume to be the lengthy part of initialization.
Sorry if talking about "lazy initialization" caused an ambiguity between the logical initialization of the component and the content of the
init
method.As to point 3, you have several options about where to complete the initialization.
On possibility is when the controller is about to be displayed. In this case, either you define
-tabBarController:didSelectViewController:
in the tab bar controller delegate, or you useviewWillAppear
. This will give you the laziest initialization of all, but it could be add some delay on the exact moment when you select the tab before the view appears.Better yet is using
viewDidLoad
, which would give you a kind of less lazy initialization; the initialization of all your controllers would happen at some point in time that you do not control (of course, before the view is displayed), so it might delay things a bit, but it would not happen inapplicationDidFinishLoading
and would be more UI-friendly since it would be controlled by the main loop. Definitely, the first option to try. Give also a look at the description ofviewDidLoad
in the UIViewController reference.Finally a note about the separate thread. Keep in mind that is not all safe using
UIKit
from a separate thread, so be careful.感觉想在这个问题上添加一个快速的 .02。正如其他人指出的那样, UIViewController 初始化和加载过程已经是“懒惰的”。真正的问题是你在初始化过程中做了什么,花了这么长时间?即使加载视图也不应该花费很长时间,因为您不希望用户在视图更改之前点击选项卡时等待。我建议如下:
在 init 中,尽可能少做一些事情。 init 的目的是初始化并准备好任何与视图无关的数据。您不应该在此处加载任何视图。
在
loadView
或viewDidLoad
中创建所有视图/子视图。仅在需要时加载数据。如果您在 init 中需要它,请将其加载到那里。如果您可以等到视图加载完毕,请在
viewDidLoad
中执行此操作。如果加载数据需要很长时间,请在后台加载。Felt like adding a quick .02 to this question. The UIViewController initialization and loading process is already "lazy" as others have pointed out. The real question is what are you doing in your initialization that is taking so long? Even loading views shouldn't take a long time as you don't want users to wait when the tap a tab before the view changes. I suggest the following:
In init, do as little as possible. The purpose of init is to have whatever view independent data initialized and ready. You should not be loading any views here.
In
loadView
orviewDidLoad
create all your views/subviews.Only load data when you need it. If you need it in init, load it there. If you can wait until the views are loaded, do it in
viewDidLoad
. If loading data takes any significant time, load it in the background.在 UIViewController 的实现中,在方法中创建所有视图
,并避免在 init 方法中创建视图(或更糟糕的是获取数据)。
默认情况下,UITabBarController 或 UINavigationController 将在用户看到它之前调用 viewDidLoad。
In your implementation of UIViewController create all your Views in the method
and avoid creating views (or even worse acquire data) in your init Method.
An UITabBarController or an UINavigationController will call the viewDidLoad by default lazy i.e. right before the user sees it.