Skip to main content

geotoolbox

GeoToolbox PlaceDescriptor patterns with MapKit integration for location representation, geocoding, and multi-service place identifiers. Use when working with place descriptors, geocoding, or cross-service location data.

Zur Installation springen

Quellinformationen

Repository
rshankras/claude-code-apple-skills
Letzte Quellaktivität
16. Juli 2026 um 14:28
Erkannte Sprache von SKILL.md
Englisch
Sterne
753
Forks
71

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
geotoolbox
description
GeoToolbox PlaceDescriptor patterns with MapKit integration for location representation, geocoding, and multi-service place identifiers. Use when working with place descriptors, geocoding, or cross-service location data.
allowed-tools
["Read","Glob","Grep"]
last_verified
2026-07-16T00:00:00.000Z
review_by
2027-06-22T00:00:00.000Z
# GeoToolbox and PlaceDescriptor Patterns Portable location representation using `PlaceDescriptor` from the GeoToolbox framework. Covers place construction from coordinates, addresses, and MapKit items; forward and reverse geocoding with the new async APIs; and multi-service place identifiers for cross-platform interop. ## When This Skill Activates Use this skill when the user: - Asks about **GeoToolbox** or **PlaceDescriptor** - Wants to represent a place with coordinates, address, or common name - Needs to convert between **MKMapItem** and **PlaceDescriptor** - Asks about **forward geocoding** (address to coordinates) or **reverse geocoding** (coordinates to address) - Wants to store or transmit **multi-service place identifiers** (Apple Maps, Google Maps, etc.) - Mentions **PlaceRepresentation**, **SupportingPlaceRepresentation**, or **MKGeocodingRequest** - Asks about portable or interoperable location data structures ## Decision Tree ``` What do you need? | +-- Represent a place with coordinates and/or address | +-- From a known coordinate | | +-- PlaceRepresentation.coordinate(CLLocationCoordinate2D) | +-- From a known address string | | +-- PlaceRepresentation.address(String) | +-- Both coordinate and address | | +-- Pass multiple representations to PlaceDescriptor | +-- From an existing MKMapItem | +-- PlaceDescriptor(item: MKMapItem) | +-- Geocode an address to coordinates | +-- MKGeocodingRequest(addressString:) | +-- try await request.mapItems | +-- Reverse geocode coordinates to an address | +-- MKReverseGeocodingRequest(location:) | +-- try await request.mapItems | +-- Attach service identifiers (Apple Maps, Google, etc.) | +-- SupportingPlaceRepresentation.serviceIdentifiers([String: String]) | +-- Read place properties +-- descriptor.coordinate, descriptor.address, descriptor.commonName +-- descriptor.serviceIdentifier(for: "com.apple.maps") ``` ## API Availability | API | Minimum OS | Import | |-----|-----------|--------| | `PlaceDescriptor` | iOS 26 / macOS 26 | `GeoToolbox` | | `PlaceRepresentation` | iOS 26 / macOS 26 | `GeoToolbox` | | `SupportingPlaceRepresentation` | iOS 26 / macOS 26 | `GeoToolbox` | | `MKGeocodingRequest` | iOS 26 / macOS 26 | `MapKit` | | `MKReverseGeocodingRequest` | iOS 26 / macOS 26 | `MapKit` | | `PlaceDescriptor(item:)` | iOS 26 / macOS 26 | `GeoToolbox` + `MapKit` | | `MKMapItem` | iOS 6 / macOS 10.9 | `MapKit` | | `CLLocationCoordinate2D` | iOS 2 / macOS 10.6 | `CoreLocation` | ## Quick Start ### Create a PlaceDescriptor from Coordinates ```swift import GeoToolbox import CoreLocation let coordinate = CLLocationCoordinate2D(latitude: 37.3349, longitude: -122.0090) let descriptor = PlaceDescriptor( representations: [.coordinate(coordinate)], commonName: "Apple Park" ) // Read back if let coord = descriptor.coordinate { print("Lat: \(coord.latitude), Lon: \(coord.longitude)") } print(descriptor.commonName ?? "No name") ``` ### Create a PlaceDescriptor from an Address ```swift import GeoToolbox let descriptor = PlaceDescriptor( representations: [.address("One Apple Park Way, Cupertino, CA 95014")], commonName: "Apple Park" ) if let address = descriptor.address { print("Address: \(address)") } ``` ### Multiple Representations and Service Identifiers ```swift import GeoToolbox import CoreLocation let coordinate = CLLocationCoordinate2D(latitude: 37.3349, longitude: -122.0090) let descriptor = PlaceDescriptor( representations: [ .coordinate(coordinate), .address("One Apple Park Way, Cupertino, CA 95014") ], commonName: "Apple Park", supportingRepresentations: [ .serviceIdentifiers([ "com.apple.maps": "apple-maps-id-12345", "com.google.maps": "ChIJ-bfVTh8_j4ARDMPaL2Njo3I" ]) ] ) // Access a specific service identifier if let appleId = descriptor.serviceIdentifier(for: "com.apple.maps") { print("Apple Maps ID: \(appleId)") } ``` ### Convert from MKMapItem ```swift import GeoToolbox import MapKit func descriptorFromMapItem(_ mapItem: MKMapItem) -> PlaceDescriptor { PlaceDescriptor(item: mapItem) } ``` ## Forward Geocoding (Address to Coordinates) ```swift import MapKit func geocodeAddress(_ addressString: String) async throws -> [MKMapItem] { let request = MKGeocodingRequest(addressString: addressString) let mapItems = try await request.mapItems return mapItems } // Usage let items = try await geocodeAddress("One Apple Park Way, Cupertino, CA") if let first = items.first { let coord = first.placemark.coordinate print("Found: \(coord.latitude), \(coord.longitude)") } ``` ## Reverse Geocoding (Coordinates to Address) ```swift import MapKit import CoreLocation func reverseGeocode(_ coordinate: CLLocationCoordinate2D) async throws -> [MKMapItem] { let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude) let request = MKReverseGeocodingRequest(location: location) let mapItems = try await request.mapItems return mapItems } // Usage let coordinate = CLLocationCoordinate2D(latitude: 37.3349, longitude: -122.0090) let items = try await reverseGeocode(coordinate) if let first = items.first { print("Address: \(first.placemark.title ?? "Unknown")") } ``` ## Full Integration Example Geocode an address, convert the result to a PlaceDescriptor with service identifiers, and read back all properties: ```swift import GeoToolbox import MapKit import CoreLocation func buildPlaceDescriptor(from addressString: String) async throws -> PlaceDescriptor? { // Forward geocode let request = MKGeocodingRequest(addressString: addressString) let mapItems = try await request.mapItems guard let mapItem = mapItems.first else { return nil } // Convert MKMapItem to PlaceDescriptor var descriptor = PlaceDescriptor(item: mapItem) // Or build manually with extra data let coordinate = mapItem.placemark.coordinate descriptor = PlaceDescriptor( representations: [ .coordinate(coordinate), .address(addressString) ], commonName: mapItem.name, supportingRepresentations: [ .serviceIdentifiers([ "com.apple.maps": "resolved-id-\(coordinate.latitude)" ]) ] ) return descriptor } func displayDescriptor(_ descriptor: PlaceDescriptor) { if let name = descriptor.commonName { print("Name: \(name)") } if let coord = descriptor.coordinate { print("Coordinate: \(coord.latitude), \(coord.longitude)") } if let address = descriptor.address { print("Address: \(address)") } if let appleId = descriptor.serviceIdentifier(for: "com.apple.maps") { print("Apple Maps ID: \(appleId)") } } ``` ## Top Mistakes | # | Mistake | Problem | Fix | |---|---------|---------|-----| | 1 | Importing only `MapKit` when using `PlaceDescriptor` | `PlaceDescriptor` lives in `GeoToolbox`, not `MapKit` | Add `import GeoToolbox` alongside `import MapKit` | | 2 | Hardcoding service identifier keys | Service identifier keys are strings; typos cause silent failures | Define constants for service keys like `"com.apple.maps"` | | 3 | Not handling geocoding errors | Network or service failures throw errors | Use `do/catch` or `try await` with proper error handling | ## Patterns ### Service Identifier Constants Define constants to avoid typos in service identifier keys: ```swift // Good -- constants prevent typos enum PlaceService { static let appleMaps = "com.apple.maps" static let googleMaps = "com.google.maps" static let foursquare = "com.foursquare" } if let id = descriptor.serviceIdentifier(for: PlaceService.appleMaps) { // use id } ``` ```swift // Bad -- raw string literals are error-prone if let id = descriptor.serviceIdentifier(for: "com.apple.map") { // typo: "map" not "maps" // silently nil } ``` ### Nil-Safe Property Access ```swift // Good -- check each optional property func formatPlace(_ descriptor: PlaceDescriptor) -> String { var parts: [String] = [] if let name = descriptor.commonName { parts.append(name) } if let address = descriptor.address { parts.append(address) } if let coord = descriptor.coordinate { parts.append("\(coord.latitude), \(coord.longitude)") } return parts.joined(separator: " -- ") } ``` ```swift // Bad -- force-unwrapping optional properties let name = descriptor.commonName! // crashes if nil let coord = descriptor.coordinate! // crashes if no coordinate representation ``` ### Geocoding with Fallback ```swift // Good -- handle empty results and errors func resolvePlace(_ address: String) async -> PlaceDescriptor? { do { let request = MKGeocodingRequest(addressString: address) let items = try await request.mapItems guard let item = items.first else { print("No results for address: \(address)") return nil } return PlaceDescriptor(item: item) } catch { print("Geocoding failed: \(error.localizedDescription)") return nil } } ``` ```swift // Bad -- no error handling, no empty check func resolvePlace(_ address: String) async -> PlaceDescriptor { let request = MKGeocodingRequest(addressString: address) let items = try! await request.mapItems // crashes on failure return PlaceDescriptor(item: items.first!) // crashes if empty } ``` ## Review Checklist - [ ] `import GeoToolbox` is present when using `PlaceDescriptor`, `PlaceRepresentation`, or `SupportingPlaceRepresentation` - [ ] `import MapKit` is present when using `MKGeocodingRequest`, `MKReverseGeocodingRequest`, or `MKMapItem` - [ ] `import CoreLocation` is present when using `CLLocationCoordinate2D` or `CLLocation` - [ ] `PlaceDescriptor` properties (`coordinate`, `address`, `commonName`) are checked for `nil` before use - [ ] Service identifier keys use defined constants, not raw string literals - [ ] `MKReverseGeocodingRequest` receives a `CLLocation`, not a raw `CLLocationCoordinate2D` - [ ] Geocoding results are checked for empty arrays before accessing elements - [ ] Geocoding calls use proper `async/await` error handling with `do/catch` - [ ] Multiple representations are provided when both coordinate and address are known - [ ] Supporting representations include service identifiers when cross-service interop is needed ## Cross-References - For **MapKit map views** and annotations, see MapKit documentation - For **CoreLocation** permissions and location updates, see CoreLocation documentation - For **SwiftUI integration** with maps, see `Map` view in SwiftUI ## References - [GeoToolbox Framework](https://developer.apple.com/documentation/geotoolbox) - [PlaceDescriptor](https://developer.apple.com/documentation/geotoolbox/placedescriptor) - [MKGeocodingRequest](https://developer.apple.com/documentation/mapkit/mkgeocodingrequest) - [MKReverseGeocodingRequest](https://developer.apple.com/documentation/mapkit/mkreversegeocodingrequest) - [MKMapItem](https://developer.apple.com/documentation/mapkit/mkmapitem)
Auf GitHub ansehen