> On Aug 23, 2016, at 4:00 PM, Tony Parker <anthony.par...@apple.com> wrote:
> 
> Hi Doug,
> 
>> On Aug 23, 2016, at 3:36 PM, Douglas Gregor via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
> 
> How do new types get added to this list? It’s certainly not the case that 
> NSValue knows about them specifically; usually some kind of category is added 
> after the fact.

I think the list was gathered from the documentation at:

        
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/
 
<https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSValue_Class/>

New types would get added when the owner of a particular framework determines 
that one of their value types can be mapped to a more-specific Objective-C 
class than Swift’s box type, at which point an _ObjectiveCBridgeable 
conformance can be added to do it. This proposal is taking the presence of 
those NSValue categories as an indication that NSValue is the best Objective-C 
class to which these types should be mapped.

> Also, how does this bridging work for swift-corelibs-foundation on Linux, 
> where bridging is disabled?

It doesn’t. This only affects how value types are boxed when we are providing 
interoperability with Objective-C.

        - Doug

> 
> - Tony
>>  
>> <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
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to