File tree Expand file tree Collapse file tree 6 files changed +82
-6
lines changed
Documentation.docc/Extensions
Documentation.docc/Articles
Tests/SwiftNavigationTests Expand file tree Collapse file tree 6 files changed +82
-6
lines changed Original file line number Diff line number Diff line change 1
1
#if canImport(SwiftUI)
2
+ import IssueReporting
2
3
import SwiftUI
3
4
4
5
extension Binding {
5
6
/// Creates a binding by projecting the base optional value to a Boolean value.
6
7
///
7
- /// Writing `false` to the binding will `nil` out the base value. Writing `true` does nothing.
8
+ /// Writing `false` to the binding will `nil` out the base value. Writing `true` produces a
9
+ /// runtime warning.
8
10
///
9
11
/// - Parameter base: A value to project to a Boolean value.
10
- public init < V> ( _ base: Binding < V ? > ) where Value == Bool {
11
- self = base. _isPresent
12
+ public init < V> (
13
+ _ base: Binding < V ? > ,
14
+ fileID: StaticString = #fileID,
15
+ filePath: StaticString = #filePath,
16
+ line: UInt = #line,
17
+ column: UInt = #column
18
+ ) where Value == Bool {
19
+ self = base [
20
+ fileID: HashableStaticString ( rawValue: fileID) ,
21
+ filePath: HashableStaticString ( rawValue: filePath) ,
22
+ line: line,
23
+ column: column
24
+ ]
12
25
}
13
26
}
14
27
15
28
extension Optional {
16
- fileprivate var _isPresent : Bool {
29
+ fileprivate subscript(
30
+ fileID fileID: HashableStaticString ,
31
+ filePath filePath: HashableStaticString ,
32
+ line line: UInt ,
33
+ column column: UInt
34
+ ) -> Bool {
17
35
get { self != nil }
18
36
set {
19
- guard !newValue else { return }
20
- self = nil
37
+ if newValue {
38
+ reportIssue (
39
+ """
40
+ Boolean presentation binding attempted to write 'true' to a generic 'Binding<Item?>' \
41
+ (i.e., 'Binding< \( Wrapped . self) ?>').
42
+
43
+ This is not a valid thing to do, as there is no way to convert 'true' to a new \
44
+ instance of ' \( Wrapped . self) '.
45
+ """ ,
46
+ fileID: fileID. rawValue,
47
+ filePath: filePath. rawValue,
48
+ line: line,
49
+ column: column
50
+ )
51
+ } else {
52
+ self = nil
53
+ }
21
54
}
22
55
}
23
56
}
Original file line number Diff line number Diff line change 8
8
- `` init(_:)-1p53m ``
9
9
- `` init(_:)-3ww0m ``
10
10
- `` init(_:)-9wed9 ``
11
+ - `` init(_:fileID:filePath:line:column:) ``
11
12
- `` init(projectedValue:) ``
12
13
- `` constant(_:) ``
13
14
17
18
- `` projectedValue ``
18
19
- `` subscript(dynamicMember:)-61aos ``
19
20
- `` subscript(dynamicMember:)-95b8x ``
21
+ - `` subscript(dynamicMember:)-xef5 ``
20
22
- `` subscript(dynamicMember:)-lmkz ``
23
+ - `` subscript(dynamicMember:)-63hti ``
21
24
22
25
### Managing changes
23
26
Original file line number Diff line number Diff line change @@ -441,6 +441,17 @@ public struct UIBinding<Value>: Sendable {
441
441
return open ( location)
442
442
}
443
443
444
+ /// Returns a Boolean binding to a case of a given case key path with no associated value.
445
+ ///
446
+ /// - Parameter keyPath: A case key path to a case with no associated value.
447
+ /// - Returns: A new binding.
448
+ public subscript< V: CasePathable > (
449
+ dynamicMember keyPath: KeyPath < V . AllCasePaths , AnyCasePath < V , Void > >
450
+ ) -> UIBinding < Bool >
451
+ where Value == V ? {
452
+ UIBinding < Bool > ( self [ dynamicMember: keyPath] )
453
+ }
454
+
444
455
/// Specifies a transaction for the binding.
445
456
///
446
457
/// - Parameter transaction: An instance of a ``UITransaction``.
Original file line number Diff line number Diff line change 29
29
self [ keyPath]
30
30
}
31
31
32
+ /// Returns a binding to a Boolean for a given case key path to a case without an associated
33
+ /// value.
34
+ ///
35
+ /// Useful for driving navigation off an optional enumeration of destinations for navigation
36
+ /// APIs that take a Boolean binding.
37
+ ///
38
+ /// - Parameter keyPath: A case key path to a specific associated value.
39
+ /// - Returns: A new binding.
40
+ public subscript< Enum: CasePathable > (
41
+ dynamicMember keyPath: KeyPath < Enum . AllCasePaths , AnyCasePath < Enum , Void > >
42
+ ) -> Binding < Bool >
43
+ where Value == Enum ? {
44
+ Binding < Bool > ( self [ keyPath] )
45
+ }
46
+
32
47
/// Creates a binding by projecting the base value to an unwrapped value.
33
48
///
34
49
/// Useful for producing non-optional bindings from optional ones.
Original file line number Diff line number Diff line change @@ -70,6 +70,7 @@ struct SignInView: View {
70
70
### Dynamic case lookup
71
71
72
72
- `` SwiftUI/Binding/subscript(dynamicMember:)-9abgy ``
73
+ - `` SwiftUI/Binding/subscript(dynamicMember:)-4i40p ``
73
74
- `` SwiftUI/Binding/subscript(dynamicMember:)-8vc80 ``
74
75
75
76
### Unwrapping bindings
Original file line number Diff line number Diff line change @@ -44,6 +44,19 @@ final class UIBindingTests: XCTestCase {
44
44
count = 1729
45
45
XCTAssertEqual ( count, 1729 )
46
46
XCTAssertEqual ( unwrappedCountBinding. wrappedValue, 1729 )
47
+
48
+ XCTExpectFailure {
49
+ let isCountPresent : UIBinding < Bool > = UIBinding ( $count)
50
+ isCountPresent. wrappedValue = true
51
+ } issueMatcher: {
52
+ $0. compactDescription == """
53
+ failed - Boolean presentation binding attempted to write 'true' to a generic 'UIBinding<Item?>' \
54
+ (i.e., 'UIBinding<Int?>').
55
+
56
+ This is not a valid thing to do, as there is no way to convert 'true' to a new instance of \
57
+ 'Int'.
58
+ """
59
+ }
47
60
}
48
61
49
62
func testOperationToOptional( ) {
You can’t perform that action at this time.
0 commit comments