> On Aug 23, 2016, at 3:44 PM, Zach Waldowski via swift-evolution
> <[email protected]> wrote:
>
> Early feedback is +1, you folks sure know how to write proposals on
> Foundation. ;-)
>
> I filed radar <rdar://problem/20807093> related to this a while ago. Is there
> any chance the struct conformances could be applied using the objc_boxable
> attribute added to Clang last year? Apple's definition of what they consider
> to be simple, fixed structs should ideally live in one place (apinotes would
> do as well).
I’d forgotten about objc_boxable. It might be possible to synthesize an
_ObjectiveCBridgeable conformance for objc_boxable types, using the @encode
string to match whether a particular NSValue can be bridged to that type.
- Doug
> Sincerely,
> Zachary Waldowski
> [email protected] <mailto:[email protected]>
>
>
> On Tue, Aug 23, 2016, at 03:36 PM, Douglas Gregor via swift-evolution wrote:
>> Introduction
>>
>> A handful of Swift numeric types are bridged to NSNumber when passed into
>> Objective-C object contexts. We should extend this bridging behavior to all
>> Swift numeric types. We should also bridge common Cocoa structs such as
>> NSRangeby boxing them into NSValue objects.
>>
>> Swift-evolution thread: TBD
>> <https://lists.swift.org/pipermail/swift-evolution/>
>>
>> <https://github.com/jckarter/swift-evolution/blob/be49e08f56450ffea394306198bcd25f58915e30/proposals/XXXX-bridge-nsnumber-and-nsvalue.md#motivation>Motivation
>>
>> SE-0116
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0116-id-as-any.md>
>> changed how Objective-C's id and untyped collections import into Swift to
>> use the Any type. This makes it much more natural to pass in Swift value
>> types such as String and Array, but introduces the hazard of passing in
>> types that don't bridge well to Objective-C objects. Particularly
>> problematic are number types; whereas Int, UInt, and Double will
>> automatically bridge as NSNumber, other-sized numeric types fall back to
>> opaque boxing:
>>
>> let i = 17
>> let plist = ["seventeen": i]
>> // OK
>> try! NSJSONSerialization.data(withJSONObject: plist)
>>
>> let j: UInt8 = 38
>> let brokenPlist = ["thirty-eight": j]
>> // Will throw because `j` didn't bridge to a JSON type
>> try! NSJSONSerialization.data(withJSONObject: brokenPlist)
>> We had shied away from enabling this bridging for all numeric types in the
>> Swift 1.x days, among other reasons because we allowed implicit bridging
>> conversions in both directions from Swift value types to NS objects and
>> back, which meant that you could slowly and brokenly convert between any two
>> numeric types transitively via NSNumber if we allowed this. We killed the
>> implicit conversions completely with SE-0072
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0072-eliminate-implicit-bridging-conversions.md>
>> so that is no longer a concern, so expanding the bridging behavior should
>> no longer be a major problem, since it must now always be explicitly asked
>> for.
>>
>> There are also many Cocoa APIs that accept NSArray and NSDictionary objects
>> with members that are NSValue-boxed structs. Matt Neuberg highlights Core
>> Automation as an example in this bug report
>> <https://bugs.swift.org/browse/SR-2414>. With id-as-Any, it's natural to
>> expect this to work:
>>
>> anim.toValue = CGPoint.zero
>> However, the CGPoint value does not box as a meaningful Objective-C object,
>> so this currently breaks Core Animation at runtime despite compiling
>> successfully. It would be more idiomatic to bridge these types to NSValue.
>>
>>
>> <https://github.com/jckarter/swift-evolution/blob/be49e08f56450ffea394306198bcd25f58915e30/proposals/XXXX-bridge-nsnumber-and-nsvalue.md#proposed-solution>Proposed
>> solution
>>
>> All of Swift's number types should be made to bridge to NSNumber when used
>> as objects in Objective-C:
>>
>> Int8
>> Int16
>> Int32
>> Int64
>> UInt8
>> UInt16
>> UInt32
>> UInt64
>> Float
>> Double
>> Cocoa structs with existing NSValue factory and property support should be
>> made to bridge to NSValue when used as objects:
>>
>> NSRange
>> CGPoint
>> CGVector
>> CGSize
>> CGRect
>> CGAffineTransform
>> UIEdgeInsets
>> UIOffset
>> CATransform3D
>> CMTime
>> CMTimeRange
>> CMTimeMapping
>> MKCoordinate
>> MKCoordinateSpan
>> SCNVector3
>> SCNVector4
>> SCNMatrix4
>>
>> <https://github.com/jckarter/swift-evolution/blob/be49e08f56450ffea394306198bcd25f58915e30/proposals/XXXX-bridge-nsnumber-and-nsvalue.md#detailed-design>Detailed
>> design
>>
>> Bridged NSNumber and NSValue objects must be castable back to their original
>> Swift value types. NSValue normally preserves the type information of its
>> included struct in its objCType property. We can check the objCType of an
>> NSValue instance when attempting to cast back to a specific bridged struct
>> type.
>>
>> NSNumber is a bit trickier, since Cocoa's implementation does not generally
>> guarantee to remember the exact number type an instance was constructed
>> from. We can instead say that casting an NSNumber to a Swift number type
>> succeeds if the value of the NSNumber is exactly representable as the target
>> type. This is imperfect, since it means that an NSNumbercan potentially be
>> cast to a different type from the original value, but it at least ensures
>> that Swift values round-trip through the bridge without depending on
>> NSNumber implementation details.
>>
>>
>> <https://github.com/jckarter/swift-evolution/blob/be49e08f56450ffea394306198bcd25f58915e30/proposals/XXXX-bridge-nsnumber-and-nsvalue.md#impact-on-existing-code>Impact
>> on existing code
>>
>> This change has no static source impact, but changes the dynamic behavior of
>> the Objective-C bridge. From Objective-C's perspective, values that used to
>> bridge as opaque objects will now come in as semantically meaningful
>> Objective-C objects. This should be a safe change, since existing code
>> should not be relying on the behavior of opaque bridged objects. From
>> Swift's perspective, values should still be able to round-trip from concrete
>> number and struct types to Anyto id to Any and back by dynamic casting. The
>> ability to reliably distinguish the exact number type that an NSNumberwas
>> constructed from would be lost.
>>
>>
>> <https://github.com/jckarter/swift-evolution/blob/be49e08f56450ffea394306198bcd25f58915e30/proposals/XXXX-bridge-nsnumber-and-nsvalue.md#alternatives-considered>Alternatives
>> considered
>>
>> We can of course do nothing and leave the behavior as-is.
>>
>> NSValue also carries factories for valueWithPointer: and
>> valueWithNonretainedObject:. Maybe we could bridgeUnsafePointer and
>> Unmanaged this way, but we probably shouldn’t.
>>
>> - Doug
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution