很抱歉,这可能不是一个编程问题,而是更多关于iOS生命周期功能性质的询问。
我有一个应用程序,我有一个函数创建四个数组并通过数据库查询填充它们。起初,我从viewDidLoad
函数调用了函数,但是,每当加载View时,在视图实际出现之前需要花费时间(大约3-4秒)。所以我做的是创建了一个activityViewIndicator
,我的viewDidLoad
函数看起来像:
- (void)viewDidLoad:(BOOL)animated{
[super viewDidLoad];
NSLog(@"viewDidLoad Entered");
[self.activityIndicatorView startAnimating];
partInput.delegate = self;
brandInput.delegate = self;
barcodeInput.delegate = self;
itemNameInput.delegate = self;
//initializeArrays is the function that initializes the arrays
[self initializeArrays];
[self.activityIndicatorView stopAnimating];
}
但是这不起作用,因为当应用程序仍在上一个视图中时会触发viewDidLoad
函数。仅在viewDidLoad
完成后才会显示视图。所以我做的是将数组初始化移动到viewDidAppear
函数,如下所示:
- (void)viewDidAppear:(BOOL)animated{
NSLog(@"viewDidAppear loaded successfully");
[self.activityIndicatorView startAnimating];
partInput.delegate = self;
brandInput.delegate = self;
barcodeInput.delegate = self;
itemNameInput.delegate = self;
[self initializeArrays];
[self.activityIndicatorView stopAnimating];
}
然而,当我部署它时,没有任何延迟,使activityIndicatorView无用。
我的问题是,为什么我认为viewDidLoad
和viewDidAppear
之间存在“性能差异”?
答案 0 :(得分:224)
请每次按照以下查看控制器生命周期。您将以这种方式对应用程序的编码和性能感到惊讶。
答案 1 :(得分:4)
我将指向Apple的文档,因为我认为需要对View Controller生命周期进行更多解释,而不仅仅是回答你的问题。
最终,您的视图控制器具有生命周期:
init - 但是您初始化视图控制器
viewWillLoad / viewDidLoad - 在构造视图时调用(通过第一次调用通过它的视图属性检索视图控制器的UIView - 也称为延迟加载)
viewWillAppear: - 当视图准备立即出现(动画==否)或查看过渡(动画==是)
viewDidAppear: - 如果未取消视图外观并且视图控制器的视图完全显示
viewWillDisappear: - 补充viewWillAppear:
viewDidDisappear: - 补充viewDidAppear:
viewWillUnload / viewDidUnload - 由于内存限制而卸载视图时不推荐使用的API(不再担心这些)
dealloc - 视图控制器本身正在被释放
最后,我相信您的问题可能是您正在使用数组初始化阻止主线程。您应该阅读异步编程,但在此期间您可以执行以下操作:
- (void)viewDidLoad
{
[super viewDidLoad];
// other stuff
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf initializeArraysSynchronously];
dispatch_async(dispatch_get_main_queue(), ^{
strongSelf.doneIntializingArrays = YES;
[strongSelf.activityIndicatorView stopAnimating];
});
}
});
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.doneInitializingArrays) {
[self.activityIndicatorView startAnimating];
}
}
答案 2 :(得分:2)
viewDidLoad:和viewDidAppear:之间绝对没有性能差异。两者都是在主线程上运行的普通函数。如果你的initializeArrays方法加载需要3秒钟,那么无论你调用哪种方法都需要3秒。由于您没有显式更改线程,因此调用initializeArrays的任何函数在完成之前都不会退出。
对[self.activityIndicatorView startAnimating]的调用将基本上“标记”activityIndicatorView,以便主线程上的另一个UI函数将启动它的动画。 (这就是主要或'UI'线程很重要的原因,因为屏幕上的所有动画和视觉更新都是相互协调的)。因此,实际获取activityIndicator的函数不会被调用,直到initializeArrays结束并且你已经调用了“stopAnimating”。
试试这个:
- (void)viewDidLoad:(BOOL)animated{
[super viewDidLoad];
NSLog(@"viewDidLoad Entered");
[self.activityIndicatorView startAnimating];
partInput.delegate = self;
brandInput.delegate = self;
barcodeInput.delegate = self;
itemNameInput.delegate = self;
}
- (void)viewDidAppear:(BOOL)animated{
//initializeArrays is the function that initializes the arrays
[self initializeArrays];
[self.activityIndicatorView stopAnimating];
}
答案 3 :(得分:1)
但是,当您从服务器(或繁重的数据处理)加载东西时,您还必须考虑延迟。如果您将所有网络通信打包到 viewDidLoad 或 viewWillAppear ,它们将在用户看到视图之前执行 - 可能会导致短冻结强大的>你的应用程序。首先向用户显示具有某种活动指示符的未填充视图可能是个好主意。当您完成网络时,可能需要一两秒钟(或者甚至可能会失败 - 谁知道?),您可以使用您的数据填充视图。在各种Twitter客户端中可以看到关于如何做到这一点的好例子。例如,当您在Twitterrific中查看作者详细信息页面时,视图仅显示“正在加载...”,直到网络查询完成。
ViewDidLoad只在您初始化ViewController但每次调用Viewdidapper时调用一次。
答案 4 :(得分:1)
activityIndicatorViews
仅在主线程(UI线程)不忙时才会生成动画。 viewDidLoad:
和viewDidAppear:
都在主线程上执行。如果你提到initializeArrays
方法没有在单独的线程中执行,那么activityIndicatorViews
将永远没有时间进行动画制作。
答案 5 :(得分:1)
查看已加载 - 第一个方法,在第一次加载视图时调用,但未在屏幕/窗口中显示,仅加载。
第一次加载视图时只调用一次。
查看显示 - 调用viewWillAppear后,将调用viewDidAppear。这意味着视图现在出现在屏幕上。
用户从该视图控制器移动到另一个视图控制器并返回时调用的次数。
**
**
1)ViewDidLoad(仅在第一次加载视图时调用),然后 2)ViewWillAppear(将被调用次数),然后 3)ViewDidAppear(将被调用次数),然后 4)ViewWillDisAppear(将被调用次数),然后 5)ViewDidDisAppear(将被调用次数)
答案 6 :(得分:0)
对于那些以编程方式进行编码(不使用Interface Builder)的人,loadView
是第一个可用的生命周期方法,而不是viewDidLoad
,并且编程开发通常比{{1}更多地使用loadView
}, 所以记住这一点。 IB的一部分工作是为您写viewDidLoad
。 IB只是缩短程序开发的一种方法,但是如果您想最好地了解Cocoa Touch,则应该以编程的方式了解它。
loadView
首先出现,通常是在其中创建UI元素的地方,包括视图控制器本身的视图(必须明确创建程序开发)。可以在这里添加约束,但是直到生命周期的后期才能处理。
loadView
通常是在建立UI元素后进行“逻辑”处理。
viewDidLoad
和viewWillAppear
在UI自身构造之前就被调用。
viewWillLayoutSubviews
接下来被调用,并且可以在实际出现之前在同一视图控制器上多次调用。这是应用自动布局的地方。这也是程序员可以在其中获取视图的安全区域值的地方,因为在此方法之前它们不可用。
viewDidLayoutSubviews
在视图控制器的视图出现在视图层次结构中之后排在最后。