diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 26fb0c9..0a1c2a3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,25 +3,29 @@ name: GEOSwiftMapKit on: push: - branches: [ main ] + branches: [main] pull_request: - branches: [ main ] + branches: [main] jobs: swiftlint: - runs-on: macos-12 + runs-on: macos-14 steps: - uses: actions/checkout@v3 + - name: Install SwiftLint + run: brew install swiftlint - name: Swiftlint - run: swiftlint + run: swiftlint --strict podspec: name: Lint Podspec for ${{ matrix.platform }} - runs-on: macos-12 + runs-on: macos-14 strategy: matrix: - platform: [ios, osx, tvos] + platform: [ios, macos, tvos] steps: - uses: actions/checkout@v3 + - name: Update CocoaPods Specs + run: pod repo update - name: Lint Podspec run: pod lib lint --platforms=${{ matrix.platform }} xcodebuild: @@ -30,46 +34,36 @@ jobs: strategy: matrix: include: - - name: "xcodebuild (iOS 16.2, Xcode 14.2)" - os: macos-12 - xcode-version: "14.2" - sdk: iphonesimulator16.2 - destination: "platform=iOS Simulator,OS=16.2,name=iPhone 14" - - name: "xcodebuild (tvOS 16.1, Xcode 14.2)" - os: macos-12 - xcode-version: "14.2" - sdk: appletvsimulator16.1 - destination: "platform=tvOS Simulator,OS=16.1,name=Apple TV" - - name: "xcodebuild (macOS 13.1, Xcode 14.2)" - os: macos-12 - xcode-version: "14.2" - sdk: macosx13.1 - destination: "platform=macOS" - - name: "xcodebuild (macCatalyst 13.1, Xcode 14.2)" - os: macos-12 - xcode-version: "14.2" - sdk: macosx13.1 - destination: "platform=macOS,variant=Mac Catalyst" - - name: "xcodebuild (iOS 15.2, Xcode 13.2.1)" - os: macos-11 - xcode-version: "13.2.1" - sdk: iphonesimulator15.2 - destination: "platform=iOS Simulator,OS=15.2,name=iPhone 13" - - name: "xcodebuild (tvOS 15.2, Xcode 13.2.1)" - os: macos-11 - xcode-version: "13.2.1" - sdk: appletvsimulator15.2 - destination: "platform=tvOS Simulator,OS=15.2,name=Apple TV" - - name: "xcodebuild (macOS 12.1, Xcode 13.2.1)" - os: macos-11 - xcode-version: "13.2.1" - sdk: macosx12.1 + - name: "xcodebuild (iOS 18.0, Xcode 16.0)" + os: macos-14 + xcode-version: "16" + sdk: iphonesimulator18.0 + destination: "platform=iOS Simulator,OS=18.0,name=iPhone 16" + - name: "xcodebuild (tvOS 18.0, Xcode 16.0)" + os: macos-14 + xcode-version: "16" + sdk: appletvsimulator18.0 + destination: "platform=tvOS Simulator,OS=18.0,name=Apple TV" + - name: "xcodebuild (macOS 15.0, Xcode 16.0)" + os: macos-14 + xcode-version: "16" + sdk: macosx15.0 + destination: "platform=OS X" + - name: "xcodebuild (iOS 17.5, Xcode 15.4)" + os: macos-14 + xcode-version: "15.4" + sdk: iphonesimulator17.5 + destination: "platform=iOS Simulator,OS=17.5,name=iPhone 15" + - name: "xcodebuild (tvOS 17.5, Xcode 15.4)" + os: macos-14 + xcode-version: "15.4" + sdk: appletvsimulator17.5 + destination: "platform=tvOS Simulator,OS=17.5,name=Apple TV" + - name: "xcodebuild (macOS 14.7, Xcode 15.4)" + os: macos-14 + xcode-version: "15.4" + sdk: macosx14.5 destination: "platform=OS X" - - name: "xcodebuild (macCatalyst 12.1, Xcode 13.2.1)" - os: macos-11 - xcode-version: "13.2.1" - sdk: macosx12.1 - destination: "platform=OS X,variant=Mac Catalyst" steps: - uses: actions/checkout@v3 - name: Select Xcode Version @@ -89,10 +83,10 @@ jobs: strategy: matrix: include: - - os: macos-11 - xcode-version: "13.2.1" - - os: macos-12 - xcode-version: "14.2" + - os: macos-14 + xcode-version: "15.4" + - os: macos-14 + xcode-version: "16" steps: - uses: actions/checkout@v3 - name: Select Xcode Version diff --git a/.gitignore b/.gitignore index 5887e4e..b286f84 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,3 @@ Carthage/Build # Swift Package Manager .build/ -.swiftpm/ diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/GEOSwiftMapKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/GEOSwiftMapKit.xcscheme new file mode 100644 index 0000000..904de4f --- /dev/null +++ b/.swiftpm/xcode/xcshareddata/xcschemes/GEOSwiftMapKit.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index ad5b1ed..b450ecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 5.0.0 + +* Updates to GEOSwift 11.0.0 +* Increases min Swift version to 5.9 +* Increases min deployment targets for Apple platforms +* Expands QuickLook support to tvOS +* Fixes some warnings when building with Xcode 16 + ## 4.0.0 * Updates to GEOSwift 10.0.0 diff --git a/GEOSwiftMapKit.podspec b/GEOSwiftMapKit.podspec index b5e28c0..05ddcf0 100644 --- a/GEOSwiftMapKit.podspec +++ b/GEOSwiftMapKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'GEOSwiftMapKit' - s.version = '4.0.0' - s.swift_version = '5.5' + s.version = '5.0.0' + s.swift_version = '5.9' s.cocoapods_version = '~> 1.10' s.summary = 'MapKit support for GEOSwift' s.description = <<~DESC @@ -15,16 +15,14 @@ Pod::Spec.new do |s| file: 'LICENSE' } s.authors = 'Andrew Hershberger' - s.platforms = { - ios: '9.0', - osx: '10.9', - tvos: '9.2', - } + s.ios.deployment_target = '12.0' + s.macos.deployment_target = '10.13' + s.tvos.deployment_target = '12.0' s.source = { git: 'https://github.com/GEOSwift/GEOSwiftMapKit.git', tag: s.version } s.source_files = 'Sources/**/*.swift' s.macos.exclude_files = 'GEOSwiftMapKit/GEOSwift+MapKitQuickLook.swift' - s.dependency 'GEOSwift', '~> 10.0' + s.dependency 'GEOSwift', '~> 11.0' end diff --git a/GEOSwiftMapKit.xctestplan b/GEOSwiftMapKit.xctestplan new file mode 100644 index 0000000..146528a --- /dev/null +++ b/GEOSwiftMapKit.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "13C39BF1-17D7-4105-AD5C-3810194BC2B3", + "name" : "Test Scheme Action", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:", + "identifier" : "GEOSwiftMapKitTests", + "name" : "GEOSwiftMapKitTests" + } + } + ], + "version" : 1 +} diff --git a/Package.resolved b/Package.resolved index a74e5cf..794e9ab 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,25 +1,23 @@ { - "object": { - "pins": [ - { - "package": "geos", - "repositoryURL": "https://github.com/GEOSwift/geos.git", - "state": { - "branch": null, - "revision": "f510e634c822116fca615064d889300dba40d761", - "version": "8.1.0" - } - }, - { - "package": "GEOSwift", - "repositoryURL": "https://github.com/GEOSwift/GEOSwift.git", - "state": { - "branch": null, - "revision": "e55eef92fb533107b43e30fcf275223a5055797e", - "version": "10.0.0" - } + "pins" : [ + { + "identity" : "geos", + "kind" : "remoteSourceControl", + "location" : "https://github.com/GEOSwift/geos.git", + "state" : { + "revision" : "4d8af495e7507f48f1ae9104102debdd2043917b", + "version" : "9.0.0" } - ] - }, - "version": 1 + }, + { + "identity" : "geoswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/GEOSwift/GEOSwift.git", + "state" : { + "revision" : "e42c062c2feb0df61373ae8cd6031a823a0dc981", + "version" : "11.0.0" + } + } + ], + "version" : 2 } diff --git a/Package.swift b/Package.swift index 52eea63..64eecbf 100644 --- a/Package.swift +++ b/Package.swift @@ -1,14 +1,14 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.9 import PackageDescription let package = Package( name: "GEOSwiftMapKit", - platforms: [.iOS(.v9), .macOS("10.9"), .tvOS("9.2")], + platforms: [.iOS(.v12), .macOS(.v10_13), .tvOS(.v12)], products: [ .library(name: "GEOSwiftMapKit", targets: ["GEOSwiftMapKit"]) ], dependencies: [ - .package(url: "https://github.com/GEOSwift/GEOSwift.git", from: "10.0.0") + .package(url: "https://github.com/GEOSwift/GEOSwift.git", from: "11.0.0") ], targets: [ .target( diff --git a/Playgrounds/GEOSwiftMapKit.playground/playground.xcworkspace/contents.xcworkspacedata b/Playgrounds/GEOSwiftMapKit.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Playgrounds/GEOSwiftMapKit.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/README.md b/README.md index 9774ec2..13d913d 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ See [GEOSwift](https://github.com/GEOSwift/GEOSwift) for full details ## Requirements -* iOS 9.0+, tvOS 9.2+, macOS 10.9+ (CocoaPods, Swift PM) -* Swift 5.5 +* iOS 12.0+, tvOS 12.0+, macOS 10.13+ (CocoaPods, Swift PM) +* Swift 5.9 > GEOS is licensed under LGPL 2.1 and its compatibility with static linking is at least controversial. Use of geos without dynamic linking is discouraged. @@ -30,7 +30,7 @@ at least controversial. Use of geos without dynamic linking is discouraged. 1. Update the top-level dependencies in your `Package.swift` to include: - .package(url: "https://github.com/GEOSwift/GEOSwiftMapKit.git", from: "4.0.0") + .package(url: "https://github.com/GEOSwift/GEOSwiftMapKit.git", from: "5.0.0") 2. Update the target dependencies in your `Package.swift` to include diff --git a/Sources/GEOSwiftMapKit/GEOSwift+MapKit.swift b/Sources/GEOSwiftMapKit/GEOSwift+MapKit.swift index d6b8fc1..6084b2c 100644 --- a/Sources/GEOSwiftMapKit/GEOSwift+MapKit.swift +++ b/Sources/GEOSwiftMapKit/GEOSwift+MapKit.swift @@ -20,7 +20,7 @@ public extension Point { public extension GEOSwift.Polygon { static var world: GEOSwift.Polygon { // swiftlint:disable:next force_try - return try! Polygon(exterior: Polygon.LinearRing(points: [ + try! Polygon(exterior: Polygon.LinearRing(points: [ Point(x: -180, y: 90), Point(x: -180, y: -90), Point(x: 180, y: -90), diff --git a/Sources/GEOSwiftMapKit/GEOSwift+MapKitQuickLook.swift b/Sources/GEOSwiftMapKit/GEOSwift+MapKitQuickLook.swift index b6cda67..3fb043d 100644 --- a/Sources/GEOSwiftMapKit/GEOSwift+MapKitQuickLook.swift +++ b/Sources/GEOSwiftMapKit/GEOSwift+MapKitQuickLook.swift @@ -1,46 +1,136 @@ -#if os(iOS) - +#if os(iOS) || os(tvOS) import UIKit import MapKit import GEOSwift -protocol GEOSwiftQuickLook: CustomPlaygroundDisplayConvertible, GeometryConvertible { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) +#if compiler(>=6) +extension Point: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } } -extension GEOSwiftQuickLook { - public var playgroundDescription: Any { - let defaultReturnValue: Any = (try? geometry.wkt()) ?? self - var bufferValue: Double = 0 - if case .point = geometry { - bufferValue = 0.1 - } - guard let buffered = try? geometry.buffer(by: bufferValue)?.intersection(with: Polygon.world), - let region = try? MKCoordinateRegion(containing: buffered) else { - return defaultReturnValue - } - let mapView = MKMapView() - mapView.mapType = .standard - mapView.frame = CGRect(x: 0, y: 0, width: 400, height: 400) - mapView.region = region - guard let image = mapView.snapshot else { - return defaultReturnValue - } - UIGraphicsBeginImageContextWithOptions(image.size, true, image.scale) - guard let context = UIGraphicsGetCurrentContext() else { - return defaultReturnValue - } - defer { UIGraphicsEndImageContext() } - image.draw(at: .zero) - quickLookDraw(in: context, imageSize: image.size, mapRect: mapView.visibleMapRect) - return UIGraphicsGetImageFromCurrentImageContext() ?? defaultReturnValue +extension MultiPoint: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension LineString: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension MultiLineString: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension GEOSwift.Polygon.LinearRing: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension GEOSwift.Polygon: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension MultiPolygon: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension GeometryCollection: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension Geometry: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension Envelope: @retroactive CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} +#else +extension Point: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension MultiPoint: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension LineString: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension MultiLineString: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension GEOSwift.Polygon.LinearRing: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension GEOSwift.Polygon: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension MultiPolygon: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension GeometryCollection: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension Geometry: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} + +extension Envelope: CustomPlaygroundDisplayConvertible { + public var playgroundDescription: Any { makePlaygroundDescription(for: self) } +} +#endif + +private func makePlaygroundDescription(for g: (some GEOSwiftQuickLook)) -> Any { + let defaultReturnValue: Any = (try? g.geometry.wkt()) ?? g + var bufferValue: Double = 0 + if case .point = g.geometry { + bufferValue = 0.1 + } + guard let buffered = try? g.geometry.buffer(by: bufferValue)?.intersection(with: Polygon.world), + let region = try? MKCoordinateRegion(containing: buffered) else { + return defaultReturnValue + } + + let options = MKMapSnapshotter.Options() + options.region = region + options.size = CGSize(width: 400, height: 400) + var snapshot: MKMapSnapshotter.Snapshot? + let backgroundQueue = DispatchQueue.global(qos: .userInitiated) + let snapshotter = MKMapSnapshotter(options: options) + let semaphore = DispatchSemaphore(value: 0) + snapshotter.start(with: backgroundQueue) { s, _ in + snapshot = s + semaphore.signal() } + _ = semaphore.wait(timeout: .now() + 3) + guard let snapshot else { + return defaultReturnValue + } + let format = UIGraphicsImageRendererFormat.preferred() + format.opaque = true + format.scale = snapshot.image.scale + return UIGraphicsImageRenderer(size: snapshot.image.size, format: format).image { context in + snapshot.image.draw(at: .zero) + g.quickLookDraw(in: context.cgContext, snapshot: snapshot) + } +} - fileprivate func draw( +private protocol GEOSwiftQuickLook: GeometryConvertible { + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) +} + +private extension GEOSwiftQuickLook { + func draw( in context: CGContext, imageSize: CGSize, mapRect: MKMapRect, - renderer: MKOverlayRenderer) { + renderer: MKOverlayRenderer + ) { context.saveGState() // scale the content to fit inside the image @@ -60,128 +150,113 @@ extension GEOSwiftQuickLook { } extension Point: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { - let pin = MKPinAnnotationView(annotation: nil, reuseIdentifier: "") - if let pinImage = pin.image { - let coord = CLLocationCoordinate2D(self) - let mapPoint = MKMapPoint(coord) - let point = CGPoint( - x: round(CGFloat((mapPoint.x - mapRect.origin.x) / mapRect.size.width) * imageSize.width), - y: round(CGFloat((mapPoint.y - mapRect.origin.y) / mapRect.size.height) * imageSize.height)) - var pinImageRect = CGRect(x: 0, y: 0, width: pinImage.size.width, height: pinImage.size.height) - pinImageRect = pinImageRect.offsetBy(dx: point.x - pinImageRect.width / 2, - dy: point.y - pinImageRect.height) - pinImage.draw(in: pinImageRect) - } + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { + let coord = CLLocationCoordinate2D(self) + let point = snapshot.point(for: coord) + let rect = CGRect(origin: point, size: .zero).insetBy(dx: -10, dy: -10) + UIColor.red.setFill() + context.fillEllipse(in: rect) } } extension MultiPoint: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { for point in points { - point.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + point.quickLookDraw(in: context, snapshot: snapshot) } } } extension LineString: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { - let polyline = MKPolyline(lineString: self) - let renderer = MKPolylineRenderer(polyline: polyline) - renderer.lineWidth = 2 - renderer.strokeColor = UIColor.blue.withAlphaComponent(0.7) - draw(in: context, imageSize: imageSize, mapRect: mapRect, renderer: renderer) + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { + UIColor.blue.withAlphaComponent(0.7).setStroke() + let path = UIBezierPath() + path.move(to: snapshot.point(for: CLLocationCoordinate2D(firstPoint))) + for point in points[1...] { + path.addLine(to: snapshot.point(for: CLLocationCoordinate2D(point))) + } + path.lineWidth = 2 + path.stroke() } } extension MultiLineString: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { for lineString in lineStrings { - lineString.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + lineString.quickLookDraw(in: context, snapshot: snapshot) } } } extension GEOSwift.Polygon.LinearRing: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { - lineString.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { + lineString.quickLookDraw(in: context, snapshot: snapshot) } } extension GEOSwift.Polygon: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { - let polygon = MKPolygon(polygon: self) - let renderer = MKPolygonRenderer(overlay: polygon) - renderer.lineWidth = 2 - renderer.strokeColor = UIColor.blue.withAlphaComponent(0.7) - renderer.fillColor = UIColor.cyan.withAlphaComponent(0.2) - draw(in: context, imageSize: imageSize, mapRect: mapRect, renderer: renderer) + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { + UIColor.blue.withAlphaComponent(0.7).setStroke() + UIColor.cyan.withAlphaComponent(0.2).setFill() + let path = UIBezierPath() + path.move(to: snapshot.point(for: CLLocationCoordinate2D(exterior.points.first!))) + for point in exterior.points[1...] { + path.addLine(to: snapshot.point(for: CLLocationCoordinate2D(point))) + } + path.close() + for hole in holes { + path.move(to: snapshot.point(for: CLLocationCoordinate2D(hole.points.first!))) + for point in hole.points[1...] { + path.addLine(to: snapshot.point(for: CLLocationCoordinate2D(point))) + } + path.close() + } + path.lineWidth = 2 + path.fill() + path.stroke() } } extension MultiPolygon: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { for polygon in polygons { - polygon.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + polygon.quickLookDraw(in: context, snapshot: snapshot) } } } extension GeometryCollection: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { for geometry in geometries { - geometry.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + geometry.quickLookDraw(in: context, snapshot: snapshot) } } } extension Geometry: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { switch self { case let .point(point): - point.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + point.quickLookDraw(in: context, snapshot: snapshot) case let .multiPoint(multiPoint): - multiPoint.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + multiPoint.quickLookDraw(in: context, snapshot: snapshot) case let .lineString(lineString): - lineString.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + lineString.quickLookDraw(in: context, snapshot: snapshot) case let .multiLineString(multiLineString): - multiLineString.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + multiLineString.quickLookDraw(in: context, snapshot: snapshot) case let .polygon(polygon): - polygon.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + polygon.quickLookDraw(in: context, snapshot: snapshot) case let .multiPolygon(multiPolygon): - multiPolygon.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + multiPolygon.quickLookDraw(in: context, snapshot: snapshot) case let .geometryCollection(geometryCollection): - geometryCollection.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) + geometryCollection.quickLookDraw(in: context, snapshot: snapshot) } } } extension Envelope: GEOSwiftQuickLook { - func quickLookDraw(in context: CGContext, imageSize: CGSize, mapRect: MKMapRect) { - geometry.quickLookDraw(in: context, imageSize: imageSize, mapRect: mapRect) - } -} - -// MARK: - MKMapView Snapshotting -private extension MKMapView { - /** - Take a snapshot of the map with MKMapSnapshot, which is designed to work in the background, - so we block the calling thread with a semaphore. - */ - var snapshot: UIImage? { - let options = MKMapSnapshotter.Options() - options.region = region - options.size = frame.size - var snapshotImage: UIImage? - let backgroundQueue = DispatchQueue.global(qos: .background) - let snapshotter = MKMapSnapshotter(options: options) - let semaphore = DispatchSemaphore(value: 0) - snapshotter.start(with: backgroundQueue) { snapshot, _ in - snapshotImage = snapshot?.image - semaphore.signal() - } - _ = semaphore.wait(timeout: .now() + 3) - return snapshotImage + func quickLookDraw(in context: CGContext, snapshot: MKMapSnapshotter.Snapshot) { + geometry.quickLookDraw(in: context, snapshot: snapshot) } } diff --git a/Tests/GEOSwiftMapKitTests/MapKit+Equatable.swift b/Tests/GEOSwiftMapKitTests/MapKit+Equatable.swift index 936f674..e16588e 100644 --- a/Tests/GEOSwiftMapKitTests/MapKit+Equatable.swift +++ b/Tests/GEOSwiftMapKitTests/MapKit+Equatable.swift @@ -1,5 +1,48 @@ import MapKit +#if compiler(>=6) +extension CLLocationCoordinate2D: @retroactive Equatable { + public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool { + lhs.latitude == rhs.latitude + && lhs.longitude == rhs.longitude + } +} + +extension MKCoordinateSpan: @retroactive Equatable { + public static func == (lhs: MKCoordinateSpan, rhs: MKCoordinateSpan) -> Bool { + lhs.latitudeDelta == rhs.latitudeDelta + && lhs.longitudeDelta == rhs.longitudeDelta + } +} + +extension MKCoordinateRegion: @retroactive Equatable { + public static func == (lhs: MKCoordinateRegion, rhs: MKCoordinateRegion) -> Bool { + lhs.center == rhs.center + && lhs.span == rhs.span + } +} + +extension MKMapPoint: @retroactive Equatable { + public static func == (lhs: MKMapPoint, rhs: MKMapPoint) -> Bool { + lhs.x == rhs.x + && lhs.y == rhs.y + } +} + +extension MKMapSize: @retroactive Equatable { + public static func == (lhs: MKMapSize, rhs: MKMapSize) -> Bool { + lhs.width == rhs.width + && lhs.height == rhs.height + } +} + +extension MKMapRect: @retroactive Equatable { + public static func == (lhs: MKMapRect, rhs: MKMapRect) -> Bool { + lhs.origin == rhs.origin + && lhs.size == rhs.size + } +} +#else extension CLLocationCoordinate2D: Equatable { public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool { lhs.latitude == rhs.latitude @@ -41,3 +84,4 @@ extension MKMapRect: Equatable { && lhs.size == rhs.size } } +#endif