为什么viewDidLoad在更新UI之前会等待?

时间:2010-02-12 09:38:24

标签: iphone objective-c

我只是试图了解iPhone上的Objective-C事件模型,以及我从根本上误解了一些事情的外观。

出于实验的目的,在视图控制器的-viewDidLoad方法中,我设置了UILabel的文本,然后睡了两秒钟,然后再次更改标签的文本。

我的期望如下:标签将首先读取“First Text”,然后两秒钟后它将更新为“Second Text”。当然,这并不是这样的。相反,视图在所有中不可见两秒钟,最后当它变为可见时,其标签显示为“Second Text。”

有人可以向我解释发生了什么事吗?我很想知道你们将如何实现我的目标。

干杯。

更新1 :这是viewDidLoad方法:

- (void)viewDidLoad {
    [super viewDidLoad];
    label.text = @"First Label";
    sleep(2);
    label.text = @"Second Label";
}

更新2 :我在这里犯了一个愚蠢的错误,所以请忽略此更新。

更新3 :我现在已将以下内容添加到我的viewDidAppear方法中:

- (void)viewDidAppear: (BOOL)animated {
    [super viewDidAppear: animated];
    label.text = @"First Label";
    sleep(2);
    label.text = @"Second Label";
}

不幸的是,我遇到了完全相同的问题。

更新4 :遵循gerry3和Felix的建议,我现在已经实现了performSelector,并且热潮!享受美食!我将不得不把它交给gerry3,因为他当然付出了最大的努力来帮助我。感谢您的所有贡献!

4 个答案:

答案 0 :(得分:4)

我想原因是viewDidLoad和所有UIKit交互一样在mainThread上运行。 UI只能在mainThread上更新,因此,如果使用sleep(2)阻止viewDidLoad,则将mainThread置于休眠状态并暂停该线程上的所有用户界面更新。

如果您想在一段时间后更新用户界面,而不是使用NSTimer,请使用sleep(2)。或者在自己上使用performSelector:withDelay:来执行某个方法,而不会阻止mainThread。

同样适用于viewDidAppearviewWillAppear。两者都在mainThread上运行。

答案 1 :(得分:3)

将您的代码修改为viewDidAppear:

中的视图

调用viewDidLoadviewWillAppear:时,视图尚未显示。

<强>更新
为了清楚起见,我同意其他人的意见,正确的方法是使用延迟的方法调用或计时器。

更新2
这是我建议的代码:

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSLog(@"View will appear!");
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSLog(@"View did appear!");

    label.text = @"First Label";
    sleep(2);
    label.text = @"Second Label";
}

和“正确”的方式:

- (void)viewDidLoad {
    [super viewDidLoad];

    label.text = @"First Label";
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    NSLog(@"View will appear!");
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSLog(@"View did appear!");

    [self performSelector:@selector(changeLabelText) withObject:nil afterDelay:2.0f];
}

- (void)changeLabelText {
    label.text = @"Second Label";
}

答案 2 :(得分:0)

我不认为你真的想在那个方法中调用sleep。这是您应该尝试并使用Timer来避免阻止UI和整个应用程序。定时器可以让您只调用一次或重复调用某些代码。有关详细信息,请参阅guide

答案 3 :(得分:0)

你的样本中viewDidAppear和viewWillAppear的签名是错误的......他们应该

- (void)viewWillAppear: (BOOL)animated {
    NSLog(@"View will appear!");
}

-(void)viewDidAppear : (BOOL)animated {
    NSLog(@"View did appear!");
}

框架不会调用带有错误签名的实现,因为消息调度找不到它们。