在旋转之前,后退按钮不会出现在导航栏中

时间:2011-10-21 21:42:39

标签: iphone objective-c ios cocoa-touch

我有三个视图控制器:A - > B - > C由导航控制器管理。 A是一个瞬态视图控制器。它要求服务器提供一些东西。如果服务器说每次访问都没问题,那么A会将B推送到堆栈上。 B必须隐藏后退按钮,因为我不希望用户手动返回A

// B view controller
- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.navigationItem.hidesBackButton = YES;
    self.title = @"B";
}
当用户点击表格单元格时,

B然后将C推送到堆栈。

// B view controller
- (void)tableView:(UITableView *)tableView 
didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    C *c = [[C alloc] 
        initWithStyle:UITableViewStyleGrouped
    ];
    [self.navigationController 
        pushViewController:c 
        animated:YES
    ];
    [c release];
}

// C view controller
- (void) viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.hidesBackButton = NO;
    self.title = @"C";
}

如果一切顺利,流程应如下所示:

-------------    -------------    -------------
|_____A_____|    |_____B ____|    | <B|__ C___|
|           | => |           | => |           |
| loading...|    |   cells   |    |   detail  |
|           |    |           |    |           |
-------------    -------------     -----------

出于某种原因,C没有显示后退按钮,以便在旋转设备之前返回B 。旋转后,后退按钮将显示在所有方向上。问题似乎源于B隐藏后退按钮和C试图再次显示它,因为如果我不让B隐藏它,我就没有这个问题。那么如何让C显示后退按钮而不强迫用户像猴子一样旋转设备?

更新

  • 在iOS 4.2.10
  • 上打破两个不同的Verizon iPhone 4
  • 在iOS 5.0上使用AT&amp; T iPhone 3GS
  • 在iOS 4.3上的AT&amp; T iPhone 4上很好

6 个答案:

答案 0 :(得分:4)

经过一番搜索后,我在一些旧的论坛帖子上找到了适用于iPhone 4.2的解决方案(因为你发布了适用于更高版本的解决方案)。

-(void)viewDidLoad { 
                     [super viewDidLoad];
                     self.navigationItem.hidesBackButton = YES; 
                   }

-(void)viewDidAppear:(BOOL)animated { 
                                       [super viewDidAppear:animated];
                                       self.navigationItem.hidesBackButton = NO; 
                                    }

也许这会帮助你。 (看看这个:Back button don't appear in navigationController

答案 1 :(得分:1)

我认为你需要把这样的代码放在C

-(void)viewDidAppear:(BOOL)animated {
      [super viewDidAppear:animated];
      self.navigationItem.hidesBackButton = NO;
}

答案 2 :(得分:0)

我曾经遇到过这个问题并通过给B的导航项目标题解决了这个问题

// B view controller
- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.navigationItem.hidesBackButton = YES;
    self.navigationItem.title = @"What you want C's back button to say";
    self.title = @"B";
}

如果您不希望标题出现在B中,您可以将B的navigationItem的titleView设置为空视图。关于titleView属性:

  

如果此属性值为nil,则当接收者为顶部项目时,导航项的标题将显示在导航栏的中心。如果将此属性设置为自定义标题,则会显示该属性而不是标题。如果leftBarButtonItem不是nil,则忽略此属性。

答案 3 :(得分:0)

尝试将self.navigationItem.hidesBackButton = NO;放入init方法或pushViewController调用之前的任何位置。

当你第一次向控制器询问视图时,会调用ViewDidLoad,也就是说,它可能是从[self.navigationController pushViewController:c animated:YES]调用的。但请注意,导航栏不是视图的一部分,它由UINavigationController创建和处理,所以基本上它甚至可以在调用viewDidLoad和viewDidAppear之前存在和绘制。如果你在那里更新导航栏,它实际上没有重新绘制。

编辑1:阅读[UIViewController navigationItem]

的文档后重新访问
  

您应该避免在导航项中创建条形按钮项目以创建视图控制器的视图。可以独立于视图控制器的视图检索视图控制器的导航项。例如,当将两个视图控制器推到导航堆栈上时,最顶层的视图控制器变得可见,但是可以检索另一个视图控制器的导航项以便呈现其后退按钮。要确保配置导航项,您可以覆盖此属性并添加代码以在其中加载条形按钮项或在视图控制器的初始化代码中加载项。

编辑2:在阅读我的解决方案不起作用的评论后重新访问。工作代码(iOS 5,ARC):


//
//  TestAppDelegate.m
//  NavigationTest
//
//  Created by Sulthan on 10/25/11.
//  Copyright (c) 2011 StackOverflow. All rights reserved.
//

#import "TestAppDelegate.h"

@interface TestAppDelegate ()

@property (nonatomic, strong, readwrite) UINavigationController* navigationScreen;

@property (nonatomic, strong, readwrite) UIViewController* screen1;
@property (nonatomic, strong, readwrite) UIViewController* screen2;
@property (nonatomic, strong, readwrite) UIViewController* screen3;

@end

@implementation TestAppDelegate

@synthesize window = window_;
@synthesize navigationScreen = navigationScreen_;
@synthesize screen1 = screen1_;
@synthesize screen2 = screen2_;
@synthesize screen3 = screen3_;

- (UIViewController*)createTestScreenWithLabel:(NSString*)label {
    CGRect bounds = [[UIScreen mainScreen] bounds];

    UIViewController* screen = [[UIViewController alloc] init];
    screen.view = [[UILabel alloc] initWithFrame:bounds];
    screen.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);

    ((UILabel*) screen.view).textAlignment = UITextAlignmentCenter;
    ((UILabel*) screen.view).text = label;

    return screen;
}

- (void)pushThirdScreen {
    if (!self.screen3) {
        self.screen3 = [self createTestScreenWithLabel:@"Screen 3"];
        self.screen3.navigationItem.hidesBackButton = NO;
    }

    [self.navigationScreen pushViewController:self.screen3 animated:YES];
}

- (void)pushSecondScreen {
    self.screen2 = [self createTestScreenWithLabel:@"Screen 2"];
    self.screen2.navigationItem.hidesBackButton = YES;

    UIBarButtonItem* button = [[UIBarButtonItem alloc] initWithTitle:@"Go"
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(pushThirdScreen)];

    self.screen2.navigationItem.rightBarButtonItem = button;

    [self.navigationScreen pushViewController:self.screen2 animated:YES];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    CGRect bounds = [[UIScreen mainScreen] bounds];

    self.screen1 = [self createTestScreenWithLabel:@"Screen 1"];

    self.navigationScreen = [[UINavigationController alloc] initWithRootViewController:self.screen1];

    self.window = [[UIWindow alloc] initWithFrame:bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window addSubview:self.navigationScreen.view];

    [self.window makeKeyAndVisible];

    [self performSelector:@selector(pushSecondScreen) withObject:nil afterDelay:3.0];

    return YES;
}

@end

编辑3:在注意到您主要讲述iOS 4.2之后重新访问。我目前无法在任何iOS 4.2上测试它,但我知道可能的解决方法。您始终可以隐藏UINavigationController中的导航栏,只需在每个屏幕中放置一个单独的导航栏即可。您可以完全控制它们,甚至可以在Interface Builder中编辑它们。

答案 4 :(得分:0)

尝试将此添加到您的班级C:

-(id) init
 {
   [super init];
   self.navigationItem.hidesBackButton = NO;
 }

答案 5 :(得分:0)

不确定这是否适用于您的后退按钮情况,但我知道当我使用自定义后退按钮时,我需要在我推动它之前在alloc'd项目上设置自定义后退按钮(不像上面的帖子那样自我)。希望它也适合你的情况 - 值得一试。

换句话说,试试:

// B view controller
- (void)tableView:(UITableView *)tableView 
didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    C *c = [[C alloc] 
        initWithStyle:UITableViewStyleGrouped];

    // *** set on c's navigationItem (not self) before you push
    [[c navigationItem] setHidesBackButton: NO];

    [self.navigationController 
        pushViewController:c 
        animated:YES
    ];

    [c release];
}