Fix iPad iOS 18 keyboard dismissal issue in search

Removed auto-focus logic that was causing keyboard show/hide loop
on iPad with docked keyboard. The keyboard was repeatedly dismissing
immediately after appearing due to interaction between keyboard
notifications, focus state changes, and view updates.

Changes:
- Removed focused state and keyboard observer from SearchModel
- Removed iOS textField reference (kept macOS only)
- Removed auto-focus logic from FocusableSearchTextField on iOS
- Cleaned up unused focus-related code

The search field now works reliably when tapped manually on iPad.
Auto-focus still works on macOS where it doesn't cause issues.
This commit is contained in:
Arkadiusz Fal
2025-11-20 17:49:10 +01:00
parent 36738572da
commit 8c5c503df2
5 changed files with 7 additions and 43 deletions

View File

@@ -318,7 +318,7 @@ final class NavigationModel: ObservableObject {
func multipleTapHandler() {
switch tabSelection {
case .search:
search.focused = true
break
default:
print("not implemented")
}

View File

@@ -16,13 +16,9 @@ final class SearchModel: ObservableObject {
@Published var querySuggestions = [String]()
private var suggestionsDebouncer = Debouncer(.milliseconds(200))
@Published var focused = false
@Default(.showSearchSuggestions) private var showSearchSuggestions
#if os(iOS)
var textField: UITextField!
#elseif os(macOS)
#if os(macOS)
var textField: NSTextField!
#endif
@@ -30,15 +26,9 @@ final class SearchModel: ObservableObject {
private var resource: Resource!
init() {
#if os(iOS)
addKeyboardDidHideNotificationObserver()
#endif
}
deinit {
#if os(iOS)
removeKeyboardDidHideNotificationObserver()
#endif
}
var isLoading: Bool {
@@ -158,18 +148,4 @@ final class SearchModel: ObservableObject {
}
}
}
#if os(iOS)
private func addKeyboardDidHideNotificationObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDidHide), name: UIResponder.keyboardDidHideNotification, object: nil)
}
@objc func onKeyboardDidHide() {
focused = false
}
private func removeKeyboardDidHideNotificationObserver() {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidHideNotification, object: nil)
}
#endif
}

View File

@@ -3,27 +3,15 @@ import SwiftUI
import SwiftUIIntrospect
struct FocusableSearchTextField: View {
@ObservedObject private var state = SearchModel.shared
var body: some View {
SearchTextField()
#if os(macOS)
.introspect(.textField, on: .macOS(.v12, .v13, .v14, .v15)) { textField in
state.textField = textField
SearchModel.shared.textField = textField
}
.onAppear {
DispatchQueue.main.async {
state.textField?.becomeFirstResponder()
}
}
#elseif os(iOS)
.introspect(.textField, on: .iOS(.v15, .v16, .v17, .v18)) { textField in
state.textField = textField
}
.onChange(of: state.focused) { newValue in
if newValue, let textField = state.textField, !textField.isFirstResponder {
textField.becomeFirstResponder()
textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)
SearchModel.shared.textField?.becomeFirstResponder()
}
}
#endif

View File

@@ -55,9 +55,9 @@ struct SearchTextField: View {
TextField("Search...", text: $state.queryText) {
state.changeQuery { query in
query.query = state.queryText
navigation.hideKeyboard()
}
RecentsModel.shared.addQuery(state.queryText)
navigation.hideKeyboard()
}
.disableAutocorrection(true)
.textFieldStyle(.plain)

View File

@@ -49,10 +49,10 @@ struct SearchView: View {
.opacity(state.queryText.isEmpty ? 0 : 1)
} else {
results
.backport
.scrollDismissesKeyboardInteractively()
}
}
.backport
.scrollDismissesKeyboardInteractively()
}
.environment(\.listingStyle, searchListingStyle)
.toolbar {