18

这是我的代码。我想在打开的 rootviewController 上放一个后退按钮。

- (void)selectSurah:(id)sender {

    SurahTableViewController * surahTableViewController = [[SurahTableViewController alloc] initWithNibName:@"SurahTableViewController" bundle:nil];
    surahTableViewController.navigationItem.title=@"Surah";

    surahTableViewController.navigationItem.backBarButtonItem.title=@"Back";

    UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:surahTableViewController];

    [self presentModalViewController:aNavigationController animated:YES];   
}
4

6 回答 6

10

我不相信有可能将根视图控制器从导航堆栈中弹出,但您可以通过UIButton添加 a 作为自定义视图来伪造它UIBarButtonItem

UIButton *b = [[UIButton alloc]initWithButtonType:UIButtonTypeCustom];
[b setImage:[UIImage imageNamed:@"BackImage.png"] forState:UIControlStateNormal];
[b addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];
self.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:b];

可以在此处找到合适的 iOS UI 元素 PSD 。

于 2012-07-01T15:50:37.547 回答
6

法赞,

Helium3评论是有道理的。

我想您的按钮需要关闭以模态方式呈现的控制器,是真的吗?如果我错了,请纠正。

如果是这样,您可以创建一个新的UIBarButtonItem并设置为UINavigationController navigationItem. 为了不破坏封装,请在控制器的viewDidLoad方法中创建它。SurahTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // make attention to memory leak if you don't use ARC!!!
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Close"
           style:UIBarButtonItemStyleBordered
             target:self
             action:@selector(close:)];
}

-(void)close:(id)sender
{
    // to dismiss use dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
    // dismissModalViewControllerAnimated: is deprecated

    [self dismissViewControllerAnimated:YES completion:^{ NSLog(@"controller dismissed"); }];
}
于 2012-07-01T15:54:04.407 回答
4

由于SurahTableViewController是导航控制器中的根视图控制器,因此您无法返回根目录,因为您已经在那里。由于您已从其他方式以模态方式呈现它,因此您需要在导航栏上放置一个按钮,该按钮具有IBAction调用功能:

[self dismissModalViewControllerAnimated:YES];
于 2012-07-01T15:51:26.920 回答
3

UINavigationController 中后退按钮的外观和行为依赖于 UINavigationController 堆栈之间的交互。在第一个控制器上放置一个后退按钮打破了这个约定,没有什么可以返回的,这就是你的代码不起作用的原因。

您需要手动将 UIBarButtonItem 添加到标题栏代码,例如:

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:self action:@selector(back:)];

如果您真的希望它看起来像一个后退按钮,您需要手动创建 UIBarButtonItem 并使用镜像后退按钮的图像。

不过,另一个建议是,因为您似乎正在尝试使用后退按钮来关闭模态视图控制器,所以我会坚持使用更传统的东西,例如“关闭”或“完成”按钮来关闭模态视图控制器。后退按钮确实更适合在 UINavigationController 堆栈中导航。

于 2012-07-01T15:49:54.037 回答
0

这是我认为每个人都在寻找的答案。

只需在自定义初始化程序中提供一个空的UIViewController作为UINavigationController子类的rootViewController 。然后在呈现之前推送您的实际rootViewController而不使用动画:

init(backButtonRootViewController: UIViewController) {
    super.init(rootViewController: UIViewController())
    
    interactivePopGestureRecognizer?.isEnabled = false
    pushViewController(backButtonRootViewController, animated: false)
}

您还需要禁用interactivePopGestureRecognizer以防止用户滑回空的rootViewController

然后扩展您的子类以实现UINavigationBarDelegate的shouldPop方法,并在rootViewController上按下后退按钮时关闭导航控制器:

func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
    
    if children.count >= 2 && children[1] == topViewController {
        presentingViewController?.dismiss(animated: true, completion: nil)
        return false
    } else {
        return true
    }
}

奇迹般有效!

于 2021-10-14T15:01:25.677 回答
0

对于 Swift,请尝试以下操作:

override func viewDidLoad() {
    super.viewDidLoad();
    self.navigationItem.hidesBackButton = true;
    let backButton = UIBarButtonItem(
        image: UIImage(named: "my_back_asset"), style: .plain,
        target: self, action: #selector(self.onBack));
    self.navigationItem.leftBarButtonItem = backButton;
}

@objc private func onBack() {
    let controller = self.navigationController?.popViewController(animated: true);
    if controller == nil {
        // Handle pressing back when on root here.
    }
}

注意将“ my_back_asset”更改为您自己的后退按钮图像。

于 2021-12-11T20:07:58.130 回答