呈现模态视图控制器会隐藏导航栏

17

我有一个带有导航栏的导航应用程序,但有一些情况下,我需要以模态的方式呈现视图控制器,而不是将其推入堆栈。问题在于,当我解除模态视图控制器时,除了按照文档所预期的隐藏导航栏并调整(父视图)大小外,其他所有功能都正常运行。因此,我想我可以简单地调用一个内置方法来取消隐藏导航栏。我已经尝试过

[self.navigationController setNavigationBarHidden:NO];

尝试使用动画版也没有成功。

文档在该方法中有所涉及。

presentModalViewController: animated:

在讨论部分中,有这样的话:

在iPhone和iPod touch设备上,模态视图控制器(modalViewController)的视图总是以全屏方式呈现"并且“将modalViewController属性设置为指定的视图控制器。调整其视图大小并将其附加到视图层次结构中。”但是,文档并没有提示我如何在关闭模态视图后撤消此过程。

还有其他人遇到过这个问题并找到了解决方案吗?

编辑:我也遇到了同样的问题,所以我赞助了这个问题的悬赏。这是我的具体情况:

在我的情况下,我正在一个导航控制器上展示一个图像选择器(Image Picker),它是在一个模态视图控制器中呈现的:

-(void) chooseImage {
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
        imagepicker = [[UIImagePickerController alloc] init];
        imagepicker.allowsEditing = NO;
        imagepicker.delegate = self;
        imagepicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        imagepicker.navigationBar.opaque = true;
        imagepicker.wantsFullScreenLayout = NO;

        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

            if (self.view.window != nil) {
                popoverController = [[UIPopoverController alloc] initWithContentViewController:imagepicker];

                [popoverController presentPopoverFromBarButtonItem:reset permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
            } else {}

        } else {
            [self.navigationController presentModalViewController:imagepicker animated:YES];   
        }
    }
}

-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [self.popoverController dismissPopoverAnimated:true];
    } else {
        [self.navigationController dismissModalViewControllerAnimated:YES];
    }
    //Save the image
}

-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        [self.popoverController dismissPopoverAnimated:true];
    } else {
        [self.navigationController dismissModalViewControllerAnimated:YES];
    }
}

你能找到这个问题的解决方案吗?我也卡在同样的问题上了... - Ankit Srivastava
作为一条注释:我也遇到了同样的问题,所以我没有提出自己的问题,而是在这个问题上设置了赏金。 - dgund
9个回答

18

确保你正在从 UINavigationController 中呈现和解散 modalViewController,就像这样:

// show
[self.navigationController presentModalViewController:vc animated:YES];
// dismiss
[self.navigationController dismissModalViewControllerAnimated:YES];
如果您的视图控制器实际上在UINavigationController的堆栈中,则这是处理模态视图控制器的演示和解除演示的正确方式。如果您的UINavigationBar仍然隐藏,那么可能还有其他问题,我们需要查看您的代码以确定发生了什么。
编辑:我将您的代码复制到我的应用程序中,UIImagePickerController成功地显示和取消,我的UINavigationController的UINavigationBar仍然存在。我真正相信问题出现在您的架构中的其他地方。如果您上传一个包含示例项目的zip文件,我会去看一下。

我必须同意Michael的观点,问题不在于你的模型视图控制器的呈现。我会查看你的视图控制器、导航控制器和模态视图控制器的viewWillAppear:viewDidAppear:viewWillDisappear:viewDidDisappear:方法,以查看它们是否以意想不到的方式操纵了UI界面。 - NSProgrammer

11

只需尝试以下代码,它将正常工作

SettingsViewController *settings    =   [[SettingsViewController alloc] init];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:settings];
[self presentModalViewController:navcont animated:YES];
[settings release];
[navcont release];

需要在呈现的控制器中展示导航控制器,才能在该控制器上拥有导航栏。


3

我认为当在错误的VC上呈现视图控制器时,会出现这种行为。您是在导航控制器还是单个VC上调用presentModalViewController吗?

如果您还没有这样做,请尝试从navigationController调用它。

[self.navigationController presentModalViewController:myVC animated:YES];

已将代码切换为使用 self.navigationController,但没有任何变化。 - dgund
本来打算接着说的,但是 Michael 先我一步了:https://dev59.com/42w05IYBdhLWcg3wxkqr#11130090 - Bob Spryn
导航栏是否真的会动画消失,还是只是在模态框覆盖时不再出现?如果您也正确地将其解除(从导航控制器),但仍无法正常工作,请在 GitHub 上发布一个我们可以修复的示例。 - Bob Spryn
当被模态视图覆盖时,它就不会返回。我已经在这个答案中添加了代码,只需要经过moderator的批准即可(对于任何不便,我感到抱歉)。简要介绍一下代码,我基本上调用了一个包含图像选取控制器的模态视图。我使用"self.navigationController"来调用和解除它。 - dgund
1
如果代码不是私有的,请考虑在GitHub上发布,以便我们实际调试它。我将查看示例代码是否出现相同的问题。 - Bob Spryn
你的代码在我的样例项目上运行正确。需要看到更多关于你的代码的细节才能找到问题。 - Bob Spryn

1

看看这个。这是苹果UIViewController类参考下的文档:

它明确提到模态视图始终以全屏模式呈现,因此很明显导航栏将被隐藏。因此,在模态视图上放置单独的导航栏以返回。

presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user.

- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
Parameters
modalViewController
The view controller that manages the modal view.
animated
If YES, animates the view as it’s presented; otherwise, does not.
Discussion
On iPhone and iPod touch devices, the view of modalViewController is always presented full screen. On iPad, the presentation depends on the value in the modalPresentationStyle property.

Sets the modalViewController property to the specified view controller. Resizes its view and attaches it to the view hierarchy. The view is animated according to the transition style specified in the modalTransitionStyle property of the controller in the modalViewController parameter.

Availability
Available in iOS 2.0 and later.

希望这可以帮助您理解,隐藏整个视图以及导航控制器是模态视图的默认行为,因此请尝试在模态视图中放置单独的导航栏进行导航。
您可以在此链接上进一步了解。

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html


感谢您的反馈。我已经多次阅读并理解了这个问题。我的问题不在于不了解模态视图是全屏显示的,而是在我取消模态视图后无法恢复导航栏的隐藏状态。我将修改问题以使之更加清晰。再次感谢。 - EmphaticArmPump
@EmphaticArmPump:但是当你呈现模态视图时,为什么需要显式隐藏导航栏呢? - Parth Bhatt
我根本没有隐藏导航栏,但是当我关闭模态视图控制器时,它就不再可见了。我只希望在关闭模态视图时它仍然可见。 - EmphaticArmPump

1

如果您将控制器作为模型呈现,视图控制器将出现在总视图中。

如果您想要通过模型视图访问导航控制器属性,则需要创建另一个导航控制器引用,并且它将继续前面的操作。

这可能对您有用。


1
AddContactVC *addController =[self.storyboard instantiateViewControllerWithIdentifier:@"AddContactVC"];
UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:addController];
[self presentViewController:navigationController animated:YES completion: nil];

在我的电脑上工作时,会显示导航栏。


0

Xcode有一个模板与你所做的非常接近。从结果来看,我认为你不应该尝试执行[self.navigationController presentModalViewController:vc]和[self.navigationController dismissModalViewControllerAnimated:],而是简单地使用[self presentModalViewController:]和[self dismissModalViewControllerAnimated:]。

要查看模板如何执行此操作,您可以在Xcode 4.3中使用新项目向导。也许它会提供一些指导:

Xcode new project wizard utility template

从这个选项中选择“下一步”,然后给你的测试项目命名,选择“通用”,关闭自动引用计数,点击下一步,在你想要保存的位置保存。

现在,点击目标并将部署目标切换到4.3(或者如果您喜欢,则为4.0)以进行测试,并切换到您的设备或iOS 4.3模拟器。

最后,在创建的AppDelegate.m文件中的applicationDidFinishLaunching:withOptions:中替换以下代码:

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.mainViewController = [[[MainViewController alloc] initWithNibName:@"MainViewController_iPhone"
                                                                        bundle:nil] autorelease];
    } else {
        self.mainViewController = [[[MainViewController alloc] initWithNibName:@"MainViewController_iPad"
                                                                        bundle:nil] autorelease];
    }
    UINavigationController* navigationController
      = [[UINavigationController alloc] initWithRootViewController:self.mainViewController];
    self.window.rootViewController = navigationController;
    [self.window makeKeyAndVisible];
    return YES;

现在,当我运行它时,它不会隐藏navigationBar。在从模板创建的MainViewController.m中,您将看到它如何从控制器本身呈现模态视图控制器并将其关闭,而不是从导航控制器中关闭。为了使模板代码更像您自己的代码,请进入MainViewController.m并删除设置模态视图控制器转换样式的行...

(当然,在iOS 5中,使用storyboard可以通过模态segues完成相同的事情...这就是我为不支持预5.0的应用程序以这种方式呈现modalViewController所做的方式。)


0

0

Emphatic和Devin -

当我开始阅读苹果文档以熟悉这个问题时,我注意到你正在使用的方法presentModalViewController:animated:已经被弃用,推荐使用presentViewController:animated:completion:。也许你应该尝试使用这个方法。

为了方便起见,请自行查看:

presentModalViewController:animated: reference

我会尝试编写一个快速测试程序,以确定我上面所说的是否正确。但是请试一试-也许会有帮助!


请注意,presentViewController:animated:completion仅适用于iOS 5.0及更高版本。而presentModalViewController:animated:自iOS 2.0以来就存在了。 - Michael Frederick
我确实需要 iOS 4.3 支持。不管怎样,这并不会改变任何事情;感谢您的建议! - dgund
1
没问题。可惜它没有帮助到你。像 @MichaelFrederick 一样,我将你的代码复制到一个随机项目中,没有发现任何问题。和他一样,我怀疑你可能有其他更隐蔽的问题。祝你好运! - ravron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接