Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve textFieldShouldReturn keyboard dismissal and docs #736

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/Orbit/Components/SegmentedSwitch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwiftUI
/// A counterpart of the native `SwiftUI.Picker` with `segmented` style applied.
///
/// A ``SegmentedSwitch`` consists of a label and two or three choices.
/// Each choice must be given an Orbit `identifier` that matches a value of the selection binding:
/// Each choice must be given an Orbit ``identifier(_:)`` that matches a value of the selection binding:
///
/// ```swift
/// enum Direction {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Orbit/Components/Tabs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwiftUI
/// A counterpart of the native `SwiftUI.Picker` with `segmented` style applied. A typical use case is switching between tabs in a native `SwiftUI.TabView`.
///
/// A ``Tabs`` consists of labels that represent specific tabs.
/// Each tab label must be given an Orbit `identifier` that matches a value of the selection binding:
/// Each tab label must be given an Orbit ``identifier(_:)`` that matches a value of the selection binding:
///
/// ```swift
/// Tabs(selection: $selectedTab) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public extension View {

/// Set the `textFieldDidBeginEditing` action for Orbit identifiable text fields.
///
/// Mark the associated Orbit text field with `identifier()` modifier to set its identity.
/// - Important: Mark the associated Orbit text field with ``identifier(_:)`` modifier to set its identity.
///
/// - Parameters:
/// - action: A handler that is executed when the user starts editing an identifiable text field inside the view hierarchy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public extension View {

/// Set the `textFieldDidEndEditing` action for Orbit identifiable text fields.
///
/// Mark the associated Orbit text field with `identifier()` modifier to set its identity.
/// - Important: Mark the associated Orbit text field with ``identifier(_:)`` modifier to set its identity.
///
/// - Parameters:
/// - action: A handler that is executed after the user ends editing a specific identifiable text field inside the view hierarchy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public extension View {

/// Set the `textFieldReturn` action for Orbit identifiable text fields.
///
/// Mark the associated Orbit text field with `identifier()` modifier to set its identity.
/// - Important: Mark the associated Orbit text field with ``identifier(_:)`` modifier to set its identity.
///
/// - Parameters:
/// - action: A handler that is executed immediately after keyboard Return action for the identifiable text field inside the view hierarchy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public extension View {

/// Set the `textField(shouldChangeCharactersIn:)` action for Orbit identifiable text fields.
///
/// Mark the associated Orbit text field with `identifier()` modifier to set its identity.
/// - Important: Mark the associated Orbit text field with ``identifier(_:)`` modifier to set its identity.
///
/// - Parameters:
/// - action: A handler that is executed for identifiable text fields inside the view hierarchy when deciding whether to change the specified text.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,29 @@ public extension EnvironmentValues {

public extension View {

/// Set the `textFieldShouldReturn` action for Orbit text fields.
/// Set the `textFieldShouldReturn` action for Orbit text fields that decides whether to process the keyboard Return button.
///
/// By default, pressing the Return button will be processed and the keyboard will be dismissed,
/// triggering the optional ``inputFieldReturnAction(_:)-9w13u`` after the processing.
///
/// If the Return button should be ignored instead, return `false` from the provided action.
/// If the focus should be switched to another field, modify the focus value in the provided action.
///
/// - Parameters:
/// - action: A handler that is executed to ask whether to process the pressing of the Return button for text fields inside the view hierarchy.
func inputFieldShouldReturnAction(_ action: @escaping () -> Bool) -> some View {
environment(\.inputFieldShouldReturnAction, action)
}

/// Set the `textFieldShouldReturn` action for Orbit identifiable text fields.
/// Set the `textFieldShouldReturn` action for Orbit identifiable text fields that decides whether to process the keyboard Return button.
///
/// By default, pressing the Return button will be processed and the keyboard will be dismissed,
/// triggering the optional ``inputFieldReturnAction(_:)-1mvv4`` after the processing.
///
/// If the Return button should be ignored instead, return `false` from the provided action.
/// If the focus should be switched to another field, modify the focus value in the provided action.
///
/// Mark the associated Orbit text field with `identifier()` modifier to set its identity.
/// - Important: Mark the associated Orbit text field with ``identifier(_:)`` modifier to set its identity.
///
/// - Parameters:
/// - action: A handler that is executed to ask whether to process the pressing of the Return button for the identifiable text field inside the view hierarchy.
Expand Down
21 changes: 20 additions & 1 deletion Sources/Orbit/Support/TextFields/TextFieldCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ public final class TextFieldCoordinator: NSObject, ObservableObject {

if shouldReturn {
DispatchQueue.main.async {
textInput.textInputView?.superview?.resignFirstResponder()
textInput.resignFirstResponder()

self.inputFieldReturnAction()

if let identifier = self.identifier {
Expand Down Expand Up @@ -299,4 +300,22 @@ extension UITextInput {
replace(textRange, withText: newValue)
}
}

/// Attempt to dismiss the keyboard.
/// Setting the @FocusState to nil in a call site has the same effect.
func resignFirstResponder() {
var attempts = 2
var view: UIView? = textInputView

while attempts > 0 {
guard let superview = view?.superview else { return }

if superview.resignFirstResponder() {
return
}

view = superview
attempts -= 1
}
}
}
Loading