> 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