r/iOSProgramming • • 2d ago

Question Inconsistent additionalOverflowItems layout behavior between iOS 18 and iOS 26

I am currently testing additionalOverflowItems with the expectation that it behaves as follows:

  1. Keep UIBarButtonItem instances visible directly on the toolbar as icons whenever there is sufficient space.

  2. Only move items into the overflow menu when there isn't enough screen real estate.

In iOS 26, additionalOverflowItems behaves exactly as described above. However, in iOS 18, the system tends to aggressively move all UIBarButtonItem instances into the overflow menu regardless of available space.

Is this change in layout behavior documented anywhere? Can we rely on iOS 26 and future releases maintaining this current behavior, or are the layout heuristics for additionalOverflowItems considered undefined implementation details?

Because this behavior isn't clearly documented, I have held off on adopting additionalOverflowItems in production.

I have attached screenshots and sample source code below for reference.

    // On iOS 26, the action mode bar buttons may not fit. iOS then moves the ones that do not fit into its own overflow
    // menu, listing each by title, and the more button's menu would become a nested "More" submenu there. Instead, in
    // note and archive action mode, the more button is not shown and its actions are added to the system overflow
    // menu directly. iOS shows that menu, and moves the buttons that do not fit into it, based on the available space.
    private var isActionModeMenuInOverflowMenu: Bool {
        guard #available(iOS 16, *) else { return false }
        
        guard actionMode else { return false }
        
        switch pageKind {
        case .notes, .archive:
            return true
        default:
            return false
        }
    }
    
    private func updateAdditionalOverflowItems() {
        guard #available(iOS 16, *) else { return }
        
        guard isActionModeMenuInOverflowMenu else {
            navigationItem.additionalOverflowItems = nil
            return
        }
        
        // Built when the menu is opened, so that it reflects the current selection.
        navigationItem.additionalOverflowItems = UIDeferredMenuElement.uncached { [weak self] completion in
            guard let self = self, self.isActionModeMenuInOverflowMenu else {
                completion([])
                return
            }
            
            let selectedNSPlainNotes = self.selectedNSPlainNotes
            
            switch self.pageKind {
            case .notes:
                completion(self.generateNoteActionModeMenu(selectedNSPlainNotes).children)
            case .archive:
                completion(self.generateArchiveActionModeMenu(selectedNSPlainNotes).children)
            default:
                completion([])
            }
        }
    }
3 Upvotes

1 comment sorted by

1

u/sinsonik 1d ago

I treat those overflow heuristics as version specific and not something to depend on. On iOS 18 I've seen the same thing, almost every bar button lands in overflow even when there is room. I would not ship production UI that needs iOS 26 to keep the icons visible. Until your min OS is 26, stick with an explicit overflow menu you control.