Skip to content

Fix index-out-of-range crash when searching the country picker - #4

Closed
jinchen1036 wants to merge 1 commit into
PhoneNumberKit:mainfrom
jinchen1036:fix/country-picker-index-out-of-range
Closed

Fix index-out-of-range crash when searching the country picker#4
jinchen1036 wants to merge 1 commit into
PhoneNumberKit:mainfrom
jinchen1036:fix/country-picker-index-out-of-range

Conversation

@jinchen1036

@jinchen1036 jinchen1036 commented Sep 8, 2026

Copy link
Copy Markdown

isFiltering is derived from the search bar (searchController.isActive && !isSearchBarEmpty), so it becomes true on the keystroke — but filteredCountries is only replaced when the throttled work item in updateSearchResults(for:) lands 0.25s later. A table view can therefore ask for a row index it read before the list changed, and the subscript traps.

Typing narrows ~250 rows across many sections down to a handful in one, so the gap between the row count UIKit last read and the array that answers is large.

country(for:) subscripted filteredCountries and countries directly. isFiltering is
derived from the search bar, so it flips on the keystroke, while filteredCountries
is only replaced when the throttled search work item lands 0.25s later. A table
view can therefore ask for a row index it read before the list changed, and the
subscript traps.

Reproduced on device in a release build:

    Fatal error: Index out of range
    CountryCodePickerViewController.country(for:)
    CountryCodePickerViewController.tableView(_:cellForRowAt:)
    -[_UIFilteredDataSource tableView:cellForRowAtIndexPath:]
    -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:]

country(for:) now returns an optional and both call sites guard. cellForRowAt
returns the dequeued cell unconfigured — the table view asks again after the
pending reload — and didSelectRowAt returns without notifying the delegate, so a
tap on a row that no longer exists cannot deliver the wrong country.

didSelectRowAt also now deselects before the guard, so the row does not stay
highlighted when the lookup misses.

country(for:) is internal and has no callers outside this file, so the signature
change is not source-breaking for clients.
@jinchen1036 jinchen1036 closed this Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant