You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中滚动ScrollView时更新导航栏返回按钮文本问题

Fixing Dynamic Back Button Text for Large/Small Navigation Titles in Swift

Great question! Let's break down why your current code isn't updating the back button text properly, then walk through two solid solutions to get this working.

Why Your Current Approach Fails

The key mistake here is understanding how backBarButtonItem works:

  • The back button displayed in your current view controller is controlled by the previous view controller in the navigation stack, not your current one.
  • When you set self.navigationItem.backBarButtonItem, you're actually defining what the back button will show when this view controller is pushed onto the stack (i.e., for the next screen), not for the current screen's back button.

That's why updating it in scrollViewDidScroll doesn't trigger an immediate change—you're modifying the wrong object.

Solution 1: Update the Previous View Controller's Back Bar Button

Since the back button is owned by the previous VC, we can directly modify its backBarButtonItem when the scroll view changes. This leverages the system's native navigation behavior without custom buttons.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard let navController = navigationController,
          navController.viewControllers.count >= 2 else {
        return // No previous VC to modify
    }
    
    // Check if we're in large title mode (adjust the height threshold if needed for your setup)
    let isLargeTitleActive = navController.navigationBar.frame.height > 59.5
    
    // Update current VC's title
    navigationItem.title = isLargeTitleActive ? "Large Title" : "Small Title"
    
    // Get the previous view controller in the stack
    let previousVC = navController.viewControllers[navController.viewControllers.count - 2]
    
    // Update its backBarButtonItem to control our current screen's back button
    previousVC.navigationItem.backBarButtonItem = UIBarButtonItem(
        title: isLargeTitleActive ? "Long Title Here" : "Back",
        style: .plain,
        target: nil,
        action: nil
    )
    
    // Force the navigation bar to refresh its layout
    navController.navigationBar.setNeedsLayout()
    navController.navigationBar.layoutIfNeeded()
}

Notes for Solution 1

  • This only works if the previous view controller hasn't set a custom leftBarButtonItem (custom left buttons override the system back button behavior).
  • The height threshold 59.5 is a common value for the transition between large (96pt) and regular (44pt) navigation bar heights, but you might need to adjust it based on your app's navigation bar setup.

Solution 2: Use a Custom Back Button

If you want full control over the back button (or if the first solution doesn't work because the previous VC uses custom buttons), you can replace the system back button with a custom one that you update directly.

First, set up the custom button in viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Hide the system back button
    navigationItem.hidesBackButton = true
    
    // Initialize the custom back button with the large title state
    updateCustomBackButton(isLargeTitle: true)
}

private func updateCustomBackButton(isLargeTitle: Bool) {
    let backText = isLargeTitle ? "Long Title Here" : "Back"
    let backButton = UIBarButtonItem(
        title: backText,
        style: .plain,
        target: self,
        action: #selector(handleBackTap)
    )
    
    // Match the system back button's appearance (optional)
    backButton.tintColor = navigationController?.navigationBar.tintColor
    
    navigationItem.leftBarButtonItem = backButton
}

@objc private func handleBackTap() {
    // Mimic the system's back behavior
    navigationController?.popViewController(animated: true)
}

Then update it in scrollViewDidScroll:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard let navController = navigationController else { return }
    
    let isLargeTitleActive = navController.navigationBar.frame.height > 59.5
    navigationItem.title = isLargeTitleActive ? "Large Title" : "Small Title"
    
    // Update the custom back button text
    updateCustomBackButton(isLargeTitle: isLargeTitleActive)
}

Notes for Solution 2

  • This gives you complete control over the back button's text, appearance, and behavior.
  • You might want to add a back arrow icon to match the system button's look—just create a UIBarButtonItem with an image and text combined, or use a custom view.

Final Tips

  • To avoid optional unwrapping headaches, consider using guard let consistently (like in the examples above) instead of force-unwrapping with !.
  • Test on different device sizes and orientations to ensure the height threshold works everywhere.

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:57:38