11
11
//===----------------------------------------------------------------------===//
12
12
13
13
#if _runtime(_ObjC)
14
- /// A Swift Array or Dictionary of types conforming to
15
- /// `_ObjectiveCBridgeable` can be passed to Objective-C as an NSArray or
16
- /// NSDictionary, respectively. The elements of the resulting NSArray
17
- /// or NSDictionary will be the result of calling `_bridgeToObjectiveC`
18
- /// on each element of the source container.
14
+ /// A protocol for value types with custom bridging behavior.
19
15
public protocol _ObjectiveCBridgeable {
16
+
17
+ /// An Objective-C type to which `Self` can be losslessly round-trip
18
+ /// converted.
20
19
associatedtype _ObjectiveCType : AnyObject
21
20
22
21
/// Convert `self` to Objective-C.
@@ -37,52 +36,160 @@ public protocol _ObjectiveCBridgeable {
37
36
result: inout Self ?
38
37
)
39
38
40
- /// Try to bridge from an Objective-C object of the bridged class
41
- /// type to a value of the Self type.
42
- ///
43
- /// This conditional bridging operation is used for conditional
44
- /// downcasting (e.g., via as?) and therefore must perform a
45
- /// complete conversion to the value type; it cannot defer checking
46
- /// to a later time.
47
- ///
48
- /// - parameter result: The location where the result is written.
49
- ///
39
+ /// Implement `x as? Self` where x is of type `_ObjectiveCType`.
40
+ ///
50
41
/// - Returns: `true` if bridging succeeded, `false` otherwise. This redundant
51
- /// information is provided for the convenience of the runtime's `dynamic_cast`
52
- /// implementation, so that it need not look into the optional representation
53
- /// to determine success.
42
+ /// information is provided for the convenience of the runtime's
43
+ /// `dynamic_cast` implementation, so that it need not look into the
44
+ /// optional representation to determine success.
45
+ ///
46
+ /// - Parameter result: a container for the new instance of `Self`.
47
+ /// - Postcondition: If ``true` is returned, `result` is non-`nil`.
54
48
@discardableResult
55
49
static func _conditionallyBridgeFromObjectiveC(
56
50
_ source: _ObjectiveCType ,
57
51
result: inout Self ?
58
52
) -> Bool
59
53
60
- /// Bridge from an Objective-C object of the bridged class type to a
61
- /// value of the Self type.
54
+ /// Convert an instance of `_ObjectiveCType?` to an instance of `Self` at an
55
+ /// imported Objective-C method boundary.
56
+ ///
57
+ /// This operation is used where an Objective-C method signature claims the
58
+ /// dynamic type of an instance is `_ObjectiveCType` with the correct
59
+ /// substructure. For example:
60
+ ///
61
+ /// @objc class ImportedClass {
62
+ /// func foo() -> [String] // -(NSArray<NSString>* _NonNull)foo
63
+ /// func bar(_ x: [String]) // -(void)bar:(NSArray<NSString>* _NonNull)
64
+ /// }
62
65
///
63
- /// This bridging operation is used for unconditional bridging when
64
- /// interoperating with Objective-C code, either in the body of an
65
- /// Objective-C thunk or when calling Objective-C code, and may
66
- /// defer complete checking until later. For example, when bridging
67
- /// from `NSArray` to `Array<Element>`, we can defer the checking
68
- /// for the individual elements of the array.
66
+ /// The Objective-C signatures claim the `NSArray*`s returned from `foo` and
67
+ /// passed to overrides of `bar` will only contain `NSString`s. We take that
68
+ /// claim on faith and do not (necessarily) check its validity. If the
69
+ /// imported signatures lie about parameter or return types, it may lead to
70
+ /// undefined behavior.
69
71
///
70
- /// \param source The Objective-C object from which we are
71
- /// bridging. This optional value will only be `nil` in cases where
72
- /// an Objective-C method has returned a `nil` despite being marked
73
- /// as `_Nonnull`/`nonnull`. In most such cases, bridging will
74
- /// generally force the value immediately. However, this gives
75
- /// bridging the flexibility to substitute a default value to cope
76
- /// with historical decisions, e.g., an existing Objective-C method
77
- /// that returns `nil` to for "empty result" rather than (say) an
78
- /// empty array. In such cases, when `nil` does occur, the
79
- /// implementation of `Swift.Array`'s conformance to
80
- /// `_ObjectiveCBridgeable` will produce an empty array rather than
81
- /// dynamically failing.
72
+ /// The signatures also claim the `NSArray*`s will be non-null, but
73
+ /// nullability is commonly mis-annotated in Objective-C. As a resilience
74
+ /// measure against mis-annotation, this method accepts `source` as an
75
+ /// `Optional`, so implementations can return an appropriate default value
76
+ /// (e.g. an empty `Array`) when `source` is `nil`.
82
77
static func _unconditionallyBridgeFromObjectiveC( _ source: _ObjectiveCType ? )
83
78
-> Self
84
79
}
85
80
81
+ public protocol _BridgePolicy {
82
+ static func bridge< Target> (
83
+ _ source: AnyObject , to target: Target . Type ) -> Target ?
84
+ }
85
+
86
+ struct _ForceCasting : _BridgePolicy {
87
+ static func bridge< Target> (
88
+ _ source: AnyObject , to target: Target . Type ) -> Target ? {
89
+ return ( source as! Target )
90
+ }
91
+ }
92
+
93
+ struct _ConditionalCasting : _BridgePolicy {
94
+ static func bridge< Target> (
95
+ _ source: AnyObject , to target: Target . Type ) -> Target ? {
96
+ return source as? Target
97
+ }
98
+ }
99
+
100
+ public protocol _CustomObjectiveCBridgeable : _ObjectiveCBridgeable {
101
+ static func _bridged< Policy: _BridgePolicy > (
102
+ from objc: _ObjectiveCType , by policy: Policy . Type ) -> Self ?
103
+
104
+ static func _bridgedFromNil( _: _ObjectiveCType ? ) -> Self
105
+ }
106
+
107
+ extension _ObjectiveCBridgeable {
108
+ public static func _bridgedFromNil( _: _ObjectiveCType ? ) -> Self {
109
+ fatalError (
110
+ " Objective-C nil of type \( String ( reflecting: _ObjectiveCType. self) ) "
111
+ + " does not bridge to \( String ( reflecting: Self . self) ) " )
112
+ }
113
+ }
114
+
115
+
116
+ extension _ObjectiveCBridgeable where Self : _CustomObjectiveCBridgeable {
117
+ /// Bridge from an Objective-C object of the bridged class type to a
118
+ /// value of the Self type.
119
+ ///
120
+ /// This bridging operation is used for forced downcasting (e.g.,
121
+ /// via as), and may defer complete checking until later. For
122
+ /// example, when bridging from `NSArray` to `Array<Element>`, we can defer
123
+ /// the checking for the individual elements of the array.
124
+ ///
125
+ /// - parameter result: The location where the result is written. The optional
126
+ /// will always contain a value.
127
+ public static func _forceBridgeFromObjectiveC(
128
+ _ source: _ObjectiveCType ,
129
+ result: inout Self ?
130
+ ) {
131
+ result = Self . _bridged (
132
+ from: source, by: _ForceCasting. self) . unsafelyUnwrapped
133
+ }
134
+
135
+ /// Implement `x as? Self` where x is of type `_ObjectiveCType`.
136
+ ///
137
+ /// - Returns: `true` if bridging succeeded, `false` otherwise. This redundant
138
+ /// information is provided for the convenience of the runtime's
139
+ /// `dynamic_cast` implementation, so that it need not look into the
140
+ /// optional representation to determine success.
141
+ ///
142
+ /// - Parameter result: a container for the new instance of `Self`.
143
+ /// - Postcondition: If ``true` is returned, `result` is non-`nil`.
144
+ @discardableResult
145
+ public static func _conditionallyBridgeFromObjectiveC(
146
+ _ source: _ObjectiveCType ,
147
+ result: inout Self ?
148
+ ) -> Bool {
149
+ result = Self . _bridged ( from: source, by: _ConditionalCasting. self)
150
+ return result != nil
151
+ }
152
+
153
+ /// Convert an instance of `_ObjectiveCType?` to an instance of `Self` at an
154
+ /// imported Objective-C method boundary.
155
+ ///
156
+ /// This operation is used where an Objective-C method signature claims the
157
+ /// dynamic type of an instance is `_ObjectiveCType` with the correct
158
+ /// substructure. For example:
159
+ ///
160
+ /// @objc class ImportedClass {
161
+ /// func foo() -> [String] // -(NSArray<NSString>* _NonNull)foo
162
+ /// func bar(_ x: [String]) // -(void)bar:(NSArray<NSString>* _NonNull)
163
+ /// }
164
+ ///
165
+ /// The Objective-C signatures claim the `NSArray*`s returned from `foo` and
166
+ /// passed to overrides of `bar` will only contain `NSString`s. We take that
167
+ /// claim on faith and do not (necessarily) check its validity. If the
168
+ /// imported signatures lie about parameter or return types, it may lead to
169
+ /// undefined behavior.
170
+ ///
171
+ /// The signatures also claim the `NSArray*`s will be non-null, but
172
+ /// nullability is commonly mis-annotated in Objective-C. As a resilience
173
+ /// measure against mis-annotation, this method accepts `source` as an
174
+ /// `Optional`, so implementations can return an appropriate default value
175
+ /// (e.g. an empty `Array`) when `source` is `nil`.
176
+ static func _unconditionallyBridgeFromObjectiveC(
177
+ _ source: _ObjectiveCType ?
178
+ ) -> Self {
179
+ if _slowPath ( source == nil ) {
180
+ return self . _bridgedFromNil ( source)
181
+ }
182
+ if let result = Self . _bridged ( from: source!, by: _ForceCasting. self) {
183
+ return result
184
+ }
185
+ fatalError (
186
+ " Bridging from Objective-C type "
187
+ + " \( String ( reflecting: _ObjectiveCType. self) ) to Swift type "
188
+ + " \( String ( reflecting: Self . self) ) failed with actual value "
189
+ + " \( String ( reflecting: source) ) " )
190
+ }
191
+ }
192
+
86
193
//===--- Bridging for metatypes -------------------------------------------===//
87
194
88
195
/// A stand-in for a value of metatype type.
0 commit comments