以模态方式呈现 UINavigationController ——在根视图控制器 viewDidLoad 中设置工具和导航栏项目时出现问题

发布于 2024-10-24 08:32:15 字数 1920 浏览 0 评论 0原文

在我的 iOS 应用程序中,我正在创建并呈现一个 UINavigationController,如下所示:

MyViewController *myvc = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil] autorelease];
UINavigationController *navVC = [[[UINavigationController alloc] initWithRootViewController:myvc] autorelease];
[self presentModalViewController:navVC animated:YES];

在 MyViewController viewDidLoad 中,我正在为导航控制器的工具栏创建和设置工具栏项目,如下所示:

self.navigationController.toolbar.items = [NSArray arrayWithObjects:(items...), nil];

我遇到的问题是这些项目不出现。相反,如果我从 MyViewController 的 viewDidLoad 方法中调用一个方法,通过 PerformSelector:withObject:afterDelay:0 添加工具栏项,那么它就可以完美工作。因此,显然这里存在一些竞争条件,包括 UINavigationController 的初始呈现、工具栏/导航栏的初始化以及导航栏指定的初始根视图控制器的初始化。

我在调试器中验证了根视图控制器的 viewDidLoad 在 UINavigationController 的 viewDidLoad 方法之后调用。事实上,根视图控制器的viewDidLoad方法直到调用presentModalViewController:时才被调用,并且UINavigationController的viewDidLoad在initWithRootViewController中被调用,所以这是否意味着UINavigationController对象应该“一切准备就绪”,包括它的导航栏和工具栏?

我一开始以为导航控制器的工具栏对象在 MyViewController 的 viewDidLoad 时可能还不存在,但它显然确实存在。至少,NSLog表明在MyViewController的viewDidLoad方法期间它不为零。事实上,UINavigationController 的工具栏对象在这两种情况下都是相同的:在根视图控制器的 viewDidLoad 中,以及在我使用 PerformSelector:withObject:afterDelay 调用的“setupToolbar”方法中,因此它不会以某种方式“重新初始化”。

那么,这是怎么回事?为什么我的工具栏修改没有“粘在”MyViewController 的 viewDidLoad 中,以及为什么在运行循环的下一次迭代中执行它们 (performSelector:withObject:afterDelay:0) 可以使其工作?

从 UINavigationController 的 rootViewController 中设置初始导航栏/工具栏项目的“正确”方法是什么?

编辑:好吧,我弄清楚发生了“什么”,尽管我仍然不明白“为什么”:在 MyViewController 的 viewDidLoad 方法返回之后(我已经验证导航控制器的工具栏的项目数组非零)和之前的某个时间/在下一个运行循环迭代中(或每当调用 PerformSelector:withObject:afterDelay:0 时),导航控制器工具栏的 items 属性设置为 nil!

编辑:调用 [self.navigationController setToolbarItems:animated:] 时遇到同样的问题

编辑:已解决,正确的方法是 [self setToolbarItems:animated:],而不是 [self.navigationController setToolbarItems:animated:],谢谢!

In my iOS app I'm creating and presenting a UINavigationController modally like so:

MyViewController *myvc = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil] autorelease];
UINavigationController *navVC = [[[UINavigationController alloc] initWithRootViewController:myvc] autorelease];
[self presentModalViewController:navVC animated:YES];

In the MyViewController viewDidLoad I'm creating and setting toolbar items for the navigation controller's toolbar, like so:

self.navigationController.toolbar.items = [NSArray arrayWithObjects:(items...), nil];

the problem I'm having is that the items don't show up. If instead I call a method from MyViewController's viewDidLoad method that adds the toolbar items via performSelector:withObject:afterDelay:0, then it works perfectly. So there's obviously some race condition going on here with the initial presentation of the UINavigationController, initialization of its toolbar/navbar, and the initialization of the nav bar's specified initial root view controller.

I verified in the debugger that the root view controller's viewDidLoad is called after the UINavigationController's viewDidLoad method. In fact, the root view controller's viewDidLoad method is not called until presentModalViewController: is called, and the UINavigationController's viewDidLoad is called within initWithRootViewController, so doesn't that imply that the UINavigationController object should be "all ready to go", including its nav bar and toolbars?

I thought at first that the navigation controller's toolbar object may not exist yet at MyViewController's viewDidLoad time, but it clearly does. At least, NSLog shows that it is not nil during MyViewController's viewDidLoad method. In fact, the UINavigationController's toolbar object is identical at both times: in the root view controller's viewDidLoad, and in the "setupToolbar" method that I called with performSelector:withObject:afterDelay, so it's not getting "re-initialized" somehow.

So, what's going on here? Why aren't my toolbar modifications "sticking" in MyViewController's viewDidLoad, and why does performing them in the next iteration of the runloop (performSelector:withObject:afterDelay:0) make it work?

What is the "right" way of setting up initial navbar / toolbar items in code from the rootViewController of the UINavigationController?

Edit: well I figured out "what" is happening, although I still don't understand the "why": after MyViewController's viewDidLoad method returns (where I have verified that the navigation controller's toolbar's items array is non-nil) and sometime before/in the next runloop iteration (or whenever a performSelector:withObject:afterDelay:0 is called), the items property of the navigation controller's toolbar is set to nil!

Edit: same problem when calling [self.navigationController setToolbarItems:animated:]

Edit: solved, the right way is [self setToolbarItems:animated:], not [self.navigationController setToolbarItems:animated:], thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晨敛清荷 2024-10-31 08:32:15

这里只是一个猜测,但是您是否尝试

[self setToolbarItems:[NSArray arrayWithObjects:(items...), nil] animated:NO];

过在 MyViewController 的 viewDidLoad 方法中使用?我不确定这是否是像您一样直接访问导航控制器工具栏的正确方法。至少 API 声明

UIViewController类参考

......

- (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated

UIViewController

由导航控制器管理的视图控制器可以使用此方法为导航控制器的内置工具栏指定工具栏项。您可以在视图控制器显示之前或可见之后设置视图控制器的工具栏项。

Just a guess here, but have you tried using

[self setToolbarItems:[NSArray arrayWithObjects:(items...), nil] animated:NO];

from within MyViewController's viewDidLoad method? I'm not sure if it's the correct way to directly access the navigation controller's toolbar like you did. At least the API states

UIViewController Class Reference

...

- (void)setToolbarItems:(NSArray *)toolbarItems animated:(BOOL)animated

...

View controllers that are managed by a navigation controller can use this method to specify toolbar items for the navigation controller’s built-in toolbar. You can set the toolbar items for your view controller before your view controller is displayed or after it is already visible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文