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() { func multipleTapHandler() {
switch tabSelection { switch tabSelection {
case .search: case .search:
search.focused = true break
default: default:
print("not implemented") print("not implemented")
} }

View File

@@ -16,13 +16,9 @@ final class SearchModel: ObservableObject {
@Published var querySuggestions = [String]() @Published var querySuggestions = [String]()
private var suggestionsDebouncer = Debouncer(.milliseconds(200)) private var suggestionsDebouncer = Debouncer(.milliseconds(200))
@Published var focused = false
@Default(.showSearchSuggestions) private var showSearchSuggestions @Default(.showSearchSuggestions) private var showSearchSuggestions
#if os(iOS) #if os(macOS)
var textField: UITextField!
#elseif os(macOS)
var textField: NSTextField! var textField: NSTextField!
#endif #endif
@@ -30,15 +26,9 @@ final class SearchModel: ObservableObject {
private var resource: Resource! private var resource: Resource!
init() { init() {
#if os(iOS)
addKeyboardDidHideNotificationObserver()
#endif
} }
deinit { deinit {
#if os(iOS)
removeKeyboardDidHideNotificationObserver()
#endif
} }
var isLoading: Bool { 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 import SwiftUIIntrospect
struct FocusableSearchTextField: View { struct FocusableSearchTextField: View {
@ObservedObject private var state = SearchModel.shared
var body: some View { var body: some View {
SearchTextField() SearchTextField()
#if os(macOS) #if os(macOS)
.introspect(.textField, on: .macOS(.v12, .v13, .v14, .v15)) { textField in .introspect(.textField, on: .macOS(.v12, .v13, .v14, .v15)) { textField in
state.textField = textField SearchModel.shared.textField = textField
} }
.onAppear { .onAppear {
DispatchQueue.main.async { DispatchQueue.main.async {
state.textField?.becomeFirstResponder() SearchModel.shared.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)
} }
} }
#endif #endif

View File

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

View File

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