+1. This is fantastic. > On Aug 23, 2016, at 5:36 PM, Douglas Gregor via swift-evolution > <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 > > <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 > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution