Files
swift-mirror/test/stdlib/MapKit.swift
Jordan Rose 7c9376db3a [SDK] Get the preferred @encode string for MapKit types dynamically (#19691)
On older OSs, CLLocationCoordinate2D was an anonymous struct with a
typedef, which meant its Objective-C type encoding string was "{?=dd}"
instead of "{CLLocationCoordinate2D=dd}". This incompatibility led to
us rejecting casts from NSValues created with CLLocationCoordinate2Ds
in Objective-C on older OSs because they didn't match the type
encoding provided. Instead, we can try to create an NSValue the way
the frameworks do, and see what /its/ type encoding is. This is what
SceneKit already does.

There's an extra wrinkle here because the convenience methods for
encoding CLLocationCoordinate2Ds are actually added in MapKit rather
than CoreLocation. That means that if someone's app just uses
CoreLocation, we can't rely on those convenience methods to get the
correct type encoding. In this case, the best thing we can do is just
give up and use the static encoding.

This whole thing is indicative of a bigger problem, namely that
NSValue normally doesn't try to validate types at all. However, Swift
bridge casting really does want to distinguish, say, a
CLLocationCoordinate2D from a CGPoint, and checking the NSValue encode
string was a way to do that. But this shows that it's still not safe
to assume that's consistent against everything in a process even if
they're all using @encode on the real struct (or the Swift
equivalent), because the different parts of the process may have been
compiled against different SDKs.

This change does not attempt to solve that problem.

Finishes rdar://problem/44866579
2018-10-03 17:31:20 -07:00

40 lines
1.3 KiB
Swift

// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop
import CoreLocation
import MapKit
import StdlibUnittest
import StdlibUnittestFoundationExtras
var mapKit = TestSuite("MapKit")
func coordinatesEqual(_ x: CLLocationCoordinate2D, _ y: CLLocationCoordinate2D)
-> Bool {
return x.latitude == y.latitude && x.longitude == y.longitude
}
func spansEqual(_ x: MKCoordinateSpan, _ y: MKCoordinateSpan)
-> Bool {
return x.latitudeDelta == y.latitudeDelta
&& x.longitudeDelta == y.longitudeDelta
}
if #available(tvOS 9.2, *) {
mapKit.test("CLLocationCoordinate2D bridging") {
expectBridgeToNSValue(CLLocationCoordinate2D(latitude: 17, longitude: 38),
nsValueInitializer: { NSValue(mkCoordinate: $0) },
nsValueGetter: { $0.mkCoordinateValue },
equal: coordinatesEqual)
}
mapKit.test("MKCoordinateSpan bridging") {
expectBridgeToNSValue(MKCoordinateSpan(latitudeDelta: 6,
longitudeDelta: 79),
nsValueInitializer: { NSValue(mkCoordinateSpan: $0) },
nsValueGetter: { $0.mkCoordinateSpanValue },
equal: spansEqual)
}
}
runAllTests()