Skip to content

Commit 7d39291

Browse files
committed
Updated README with notes on new APIs
1 parent 54b83cd commit 7d39291

File tree

1 file changed

+58
-4
lines changed

1 file changed

+58
-4
lines changed

README.md

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,30 +237,78 @@ major pieces of missing behaviour from the native `TextField` type.
237237
### Observing the first responder state
238238

239239
When initialised you can pass in a callback function using the parameter
240-
`onFirstResponderStateChanged:` - this takes a closure that will be called
241-
with the updated `FirstResponderState` whenever it changes, either as a result
240+
`onFirstResponderStateChanged:` - this takes a value of type
241+
`FirstResponderStateChangeHandler`, which wraps a closure that will be called
242+
with the updated first responder state whenever it changes, either as a result
242243
of some user interaction or as the result of a change in the
243244
`FirstResponderDemand` (see below).
244245

246+
The first responder state is represented as a single `Bool` value where `true`
247+
indicates that the text field has become first responder and `false` indicates
248+
that it has resigned first responder.
249+
250+
```swift
251+
struct ExampleView: View {
252+
var body: some View {
253+
ResponsiveTextField(
254+
placeholder: "Email address",
255+
text: $email,
256+
configuration: .emailField,
257+
onFirstResponderStateChanged: .init { isFirstResponder in
258+
// do something with first responder state
259+
}
260+
)
261+
}
262+
}
263+
245264
If you need to track this state you can store it in some external state, such as
246265
an `@State` property or an `@ObservableObject` (like your view model):
247266

248267
```swift
249268
struct ExampleView: View {
250269
@State
251-
var responderState: FirstResponderState = .notFirstResponder
270+
var isFirstResponder = false
252271

253272
var body: some View {
254273
ResponsiveTextField(
255274
placeholder: "Email address",
256275
text: $email,
257276
configuration: .emailField,
258-
onFirstResponderStateChanged: { responderState = $0 }
277+
onFirstResponderStateChanged: .init {
278+
isFirstResponder = $0
279+
}
259280
)
260281
}
261282
}
262283
```
263284

285+
If all you need to do is update some external state, you can use the built-in
286+
`.updates` state changed handler, passing in a binding to that state. The above
287+
example can be simplified to:
288+
289+
```swift
290+
struct ExampleView: View {
291+
@State
292+
var isFirstResponder = false
293+
294+
var body: some View {
295+
ResponsiveTextField(
296+
placeholder: "Email address",
297+
text: $email,
298+
configuration: .emailField,
299+
onFirstResponderStateChanged: .updates($isFirstResponder)
300+
)
301+
}
302+
}
303+
```
304+
305+
`FirstResponderStateChangeHandler` can also be initialised with a
306+
`canBecomeFirstResponder` and `canResignFirstResponder` closures that both
307+
return a `Bool` - if provided, these will be called in the text field's
308+
`shouldBeginEditing` and `shouldEndEditing` delegate calls and provide flexible
309+
control over if the text field's responder state should change. If these
310+
closures are not provided these delegate methods will return `true`.
311+
264312
### Progamatically controlling the first responder state
265313

266314
`ResponsiveTextField` also supports binding-based control over the field's
@@ -384,6 +432,12 @@ struct ExampleView: View {
384432
}
385433
```
386434

435+
When using programatic responder state demands and the `canBecomeFirstResponder`
436+
and `canResignFirstResponder` closures on `FirstResponderStateChangeHandler`,
437+
its important to note that the latter will take priority. If either of these
438+
closures return `false`, the demand will be ignored and marked as fulfilled,
439+
resetting it back to `nil`.
440+
387441
## Licence
388442

389443
This library is released under the Apache v2.0 license. See [LICENSE](LICENSE)

0 commit comments

Comments
 (0)