{"id":"d49d7900-4974-4b94-b62f-766331f887a1","shortId":"2WR6HX","kind":"skill","title":"mapkit","tagline":"Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, annotations, markers, polylines, user location tracking, geocoding, reverse geocoding, search/autocomplete, directions and routes, geofencing","description":"# MapKit\n\nBuild map-based and location-aware features targeting iOS 17+ with SwiftUI\nMapKit and modern CoreLocation async APIs. Use `Map` with `MapContentBuilder`\nfor views, `CLLocationUpdate.liveUpdates()` for streaming location, and\n`CLMonitor` for geofencing.\n\nSee [references/mapkit-patterns.md](references/mapkit-patterns.md) for extended MapKit patterns and\n[references/mapkit-corelocation-patterns.md](references/mapkit-corelocation-patterns.md) for CoreLocation patterns.\n\n## Contents\n\n- [Workflow](#workflow)\n- [SwiftUI Map View (iOS 17+)](#swiftui-map-view-ios-17)\n- [CoreLocation Modern API](#corelocation-modern-api)\n- [Geocoding](#geocoding)\n- [Search](#search)\n- [Directions](#directions)\n- [PlaceDescriptor (iOS 26+)](#placedescriptor-ios-26)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Workflow\n\n### 1. Add a map with markers or annotations\n\n1. Import `MapKit`.\n2. Create a `Map` view with optional `MapCameraPosition` binding.\n3. Add `Marker`, `Annotation`, `MapPolyline`, `MapPolygon`, or `MapCircle`\n   inside the `MapContentBuilder` closure.\n4. Configure map style with `.mapStyle()`.\n5. Add map controls with `.mapControls { }`.\n6. Handle selection with a `selection:` binding.\n\n### 2. Track user location\n\n1. Add `NSLocationWhenInUseUsageDescription` to Info.plist.\n2. On iOS 18+, create a `CLServiceSession` to manage authorization.\n3. Iterate `CLLocationUpdate.liveUpdates()` in a `Task`.\n4. Filter updates by distance or accuracy before updating the UI.\n5. Stop the task when location tracking is no longer needed.\n\n### 3. Search for places\n\n1. Configure `MKLocalSearchCompleter` for autocomplete suggestions.\n2. Debounce user input (at least 300ms) before setting the query.\n3. Convert selected completion to `MKLocalSearch.Request` for full results.\n4. Display results as markers or in a list.\n\n### 4. Get directions and display a route\n\n1. Create an `MKDirections.Request` with source and destination `MKMapItem`.\n2. Set `transportType` (`.automobile`, `.walking`, `.transit`, `.cycling`).\n3. Await `MKDirections.calculate()`.\n4. Draw the route with `MapPolyline(route.polyline)`.\n\n### 5. Review existing map/location code\n\nRun through the Review Checklist at the end of this file.\n\n## SwiftUI Map View (iOS 17+)\n\n```swift\nimport MapKit\nimport SwiftUI\n\nstruct PlaceMap: View {\n    @State private var position: MapCameraPosition = .automatic\n\n    var body: some View {\n        Map(position: $position) {\n            Marker(\"Apple Park\", coordinate: applePark)\n            Marker(\"Infinite Loop\", systemImage: \"building.2\",\n                   coordinate: infiniteLoop)\n        }\n        .mapStyle(.standard(elevation: .realistic))\n        .mapControls {\n            MapUserLocationButton()\n            MapCompass()\n            MapScaleView()\n        }\n    }\n}\n```\n\n### Marker and Annotation\n\n```swift\n// Balloon marker -- simplest way to pin a location\nMarker(\"Cafe\", systemImage: \"cup.and.saucer.fill\", coordinate: cafeCoord)\n    .tint(.brown)\n\n// Annotation -- custom SwiftUI view at a coordinate\nAnnotation(\"You\", coordinate: userCoord, anchor: .bottom) {\n    Image(systemName: \"figure.wave\")\n        .padding(6)\n        .background(.blue.gradient, in: .circle)\n        .foregroundStyle(.white)\n}\n```\n\n### Overlays: Polyline, Polygon, Circle\n\n```swift\nMap {\n    // Polyline from coordinates\n    MapPolyline(coordinates: routeCoords)\n        .stroke(.blue, lineWidth: 4)\n\n    // Polygon (area highlight)\n    MapPolygon(coordinates: parkBoundary)\n        .foregroundStyle(.green.opacity(0.3))\n        .stroke(.green, lineWidth: 2)\n\n    // Circle (radius around a point)\n    MapCircle(center: storeCoord, radius: 500)\n        .foregroundStyle(.red.opacity(0.15))\n        .stroke(.red, lineWidth: 1)\n}\n```\n\n### Camera Position\n\n`MapCameraPosition` controls what the map displays. Bind it to let the user\ninteract and to programmatically move the camera.\n\n```swift\n// Center on a region\n@State private var position: MapCameraPosition = .region(\n    MKCoordinateRegion(\n        center: CLLocationCoordinate2D(latitude: 37.334, longitude: -122.009),\n        span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)\n    )\n)\n\n// Follow user location\n@State private var position: MapCameraPosition = .userLocation(fallback: .automatic)\n\n// Specific camera angle (3D perspective)\n@State private var position: MapCameraPosition = .camera(\n    MapCamera(centerCoordinate: applePark, distance: 1000, heading: 90, pitch: 60)\n)\n\n// Frame specific items\nposition = .item(MKMapItem.forCurrentLocation())\nposition = .rect(MKMapRect(...))\n```\n\n### Map Style\n\n```swift\n.mapStyle(.standard)                                        // Default road map\n.mapStyle(.standard(elevation: .realistic, showsTraffic: true))\n.mapStyle(.imagery)                                         // Satellite\n.mapStyle(.imagery(elevation: .realistic))                  // 3D satellite\n.mapStyle(.hybrid)                                          // Satellite + labels\n.mapStyle(.hybrid(elevation: .realistic, showsTraffic: true))\n```\n\n### Map Interaction Modes\n\n```swift\n.mapInteractionModes(.all)           // Default: pan, zoom, rotate, pitch\n.mapInteractionModes(.pan)           // Pan only\n.mapInteractionModes([.pan, .zoom])  // Pan and zoom\n.mapInteractionModes([])             // Static map (no interaction)\n```\n\n### Map Selection\n\n```swift\n@State private var selectedMarker: MKMapItem?\n\nMap(selection: $selectedMarker) {\n    ForEach(places) { place in\n        Marker(place.name, coordinate: place.coordinate)\n            .tag(place.mapItem)     // Tag must match selection type\n    }\n}\n.onChange(of: selectedMarker) { _, newValue in\n    guard let item = newValue else { return }\n    // React to selection\n}\n```\n\n## CoreLocation Modern API\n\n### CLLocationUpdate.liveUpdates() (iOS 17+)\n\nReplace `CLLocationManagerDelegate` callbacks with a single async sequence.\nEach iteration yields a `CLLocationUpdate` containing an optional `CLLocation`.\n\n```swift\nimport CoreLocation\n\n@Observable\nfinal class LocationTracker: @unchecked Sendable {\n    var currentLocation: CLLocation?\n    private var updateTask: Task<Void, Never>?\n\n    func startTracking() {\n        updateTask = Task {\n            let updates = CLLocationUpdate.liveUpdates()\n            for try await update in updates {\n                guard let location = update.location else { continue }\n                // Filter by horizontal accuracy\n                guard location.horizontalAccuracy < 50 else { continue }\n                await MainActor.run {\n                    self.currentLocation = location\n                }\n            }\n        }\n    }\n\n    func stopTracking() {\n        updateTask?.cancel()\n        updateTask = nil\n    }\n}\n```\n\n### CLServiceSession (iOS 18+)\n\nDeclare authorization requirements for a feature's lifetime. Hold a reference\nto the session for as long as you need location services.\n\n```swift\n// When-in-use authorization with full accuracy preference\nlet session = CLServiceSession(\n    authorization: .whenInUse,\n    fullAccuracyPurposeKey: \"NearbySearchPurpose\"\n)\n// Hold `session` as a stored property; release it when done.\n```\n\nOn iOS 18+, `CLLocationUpdate.liveUpdates()` and `CLMonitor` take an implicit\n`CLServiceSession` if you do not create one explicitly. Create one explicitly\nwhen you need `.always` authorization or full accuracy.\n\n### Authorization Flow\n\n```swift\n// Info.plist keys (required):\n// NSLocationWhenInUseUsageDescription\n// NSLocationAlwaysAndWhenInUseUsageDescription (only if .always needed)\n\n// Check authorization and guide user to Settings when denied\nstruct LocationPermissionView: View {\n    @Environment(\\.openURL) private var openURL\n\n    var body: some View {\n        ContentUnavailableView {\n            Label(\"Location Access Denied\", systemImage: \"location.slash\")\n        } description: {\n            Text(\"Enable location access in Settings to use this feature.\")\n        } actions: {\n            Button(\"Open Settings\") {\n                if let url = URL(string: UIApplication.openSettingsURLString) {\n                    openURL(url)\n                }\n            }\n        }\n    }\n}\n```\n\n## Geocoding\n\n### CLGeocoder (iOS 8+)\n\n```swift\nlet geocoder = CLGeocoder()\n\n// Forward geocoding: address string -> coordinates\nlet placemarks = try await geocoder.geocodeAddressString(\"1 Apple Park Way, Cupertino\")\nif let location = placemarks.first?.location {\n    print(location.coordinate) // CLLocationCoordinate2D\n}\n\n// Reverse geocoding: coordinates -> placemark\nlet location = CLLocation(latitude: 37.3349, longitude: -122.0090)\nlet placemarks = try await geocoder.reverseGeocodeLocation(location)\nif let placemark = placemarks.first {\n    let address = [placemark.name, placemark.locality, placemark.administrativeArea]\n        .compactMap { $0 }\n        .joined(separator: \", \")\n}\n```\n\n### MKGeocodingRequest and MKReverseGeocodingRequest (iOS 26+)\n\nNew MapKit-native geocoding that returns `MKMapItem` with richer data and\n`MKAddress` / `MKAddressRepresentations` for flexible address formatting.\n\n```swift\n@available(iOS 26, *)\nfunc reverseGeocode(location: CLLocation) async throws -> MKMapItem? {\n    guard let request = MKReverseGeocodingRequest(location: location) else {\n        return nil\n    }\n    let mapItems = try await request.mapItems\n    return mapItems.first\n}\n\n@available(iOS 26, *)\nfunc forwardGeocode(address: String) async throws -> [MKMapItem] {\n    guard let request = MKGeocodingRequest(addressString: address) else { return [] }\n    return try await request.mapItems\n}\n```\n\n## Search\n\n### MKLocalSearchCompleter (Autocomplete)\n\n```swift\n@Observable\nfinal class SearchCompleter: NSObject, MKLocalSearchCompleterDelegate {\n    var results: [MKLocalSearchCompletion] = []\n    var query: String = \"\" { didSet { completer.queryFragment = query } }\n\n    private let completer = MKLocalSearchCompleter()\n\n    override init() {\n        super.init()\n        completer.delegate = self\n        completer.resultTypes = [.address, .pointOfInterest]\n    }\n\n    func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {\n        results = completer.results\n    }\n\n    func completer(_ completer: MKLocalSearchCompleter, didFailWithError error: Error) {\n        results = []\n    }\n}\n```\n\n### MKLocalSearch (Full Search)\n\n```swift\nfunc search(for completion: MKLocalSearchCompletion) async throws -> [MKMapItem] {\n    let request = MKLocalSearch.Request(completion: completion)\n    request.resultTypes = [.pointOfInterest, .address]\n    let search = MKLocalSearch(request: request)\n    let response = try await search.start()\n    return response.mapItems\n}\n\n// Search by natural language query within a region\nfunc searchNearby(query: String, region: MKCoordinateRegion) async throws -> [MKMapItem] {\n    let request = MKLocalSearch.Request()\n    request.naturalLanguageQuery = query\n    request.region = region\n    let search = MKLocalSearch(request: request)\n    let response = try await search.start()\n    return response.mapItems\n}\n```\n\n## Directions\n\n```swift\nfunc getDirections(from source: MKMapItem, to destination: MKMapItem,\n                   transport: MKDirectionsTransportType = .automobile) async throws -> MKRoute? {\n    let request = MKDirections.Request()\n    request.source = source\n    request.destination = destination\n    request.transportType = transport\n    let directions = MKDirections(request: request)\n    let response = try await directions.calculate()\n    return response.routes.first\n}\n```\n\n### Display Route on Map\n\n```swift\n@State private var route: MKRoute?\n\nMap {\n    if let route {\n        MapPolyline(route.polyline)\n            .stroke(.blue, lineWidth: 5)\n    }\n    Marker(\"Start\", coordinate: startCoord)\n    Marker(\"End\", coordinate: endCoord)\n}\n.task {\n    route = try? await getDirections(from: startItem, to: endItem)\n}\n```\n\n### ETA Calculation\n\n```swift\nfunc getETA(from source: MKMapItem, to destination: MKMapItem) async throws -> TimeInterval {\n    let request = MKDirections.Request()\n    request.source = source\n    request.destination = destination\n    let directions = MKDirections(request: request)\n    let response = try await directions.calculateETA()\n    return response.expectedTravelTime\n}\n```\n\n### Cycling Directions (iOS 26+)\n\n```swift\n@available(iOS 26, *)\nfunc getCyclingDirections(to destination: MKMapItem) async throws -> MKRoute? {\n    let request = MKDirections.Request()\n    request.source = MKMapItem.forCurrentLocation()\n    request.destination = destination\n    request.transportType = .cycling\n    let directions = MKDirections(request: request)\n    let response = try await directions.calculate()\n    return response.routes.first\n}\n```\n\n## PlaceDescriptor (iOS 26+)\n\nCreate rich place references from coordinates or addresses without needing a\nPlace ID. Requires `import GeoToolbox`.\n\n```swift\n@available(iOS 26, *)\nfunc lookupPlace(name: String, coordinate: CLLocationCoordinate2D) async throws -> MKMapItem {\n    let descriptor = PlaceDescriptor(\n        representations: [.coordinate(coordinate)],\n        commonName: name\n    )\n    let request = MKMapItemRequest(placeDescriptor: descriptor)\n    return try await request.mapItem\n}\n```\n\n## Common Mistakes\n\n**DON'T:** Request `.authorizedAlways` upfront — users distrust broad permissions.\n**DO:** Start with `.requestWhenInUseAuthorization()`, escalate to `.always` only when the user enables a background feature.\n\n**DON'T:** Use `CLLocationManagerDelegate` for simple location fetches on iOS 17+.\n**DO:** Use `CLLocationUpdate.liveUpdates()` async stream for cleaner, more concise code.\n\n**DON'T:** Keep location updates running when the map/view is not visible (drains battery).\n**DO:** Use `.task { }` in SwiftUI so updates cancel automatically on disappear.\n\n**DON'T:** Force-unwrap `CLPlacemark` properties — they are all optional.\n**DO:** Use nil-coalescing: `placemark.locality ?? \"Unknown\"`.\n\n**DON'T:** Fire `MKLocalSearchCompleter` queries on every keystroke.\n**DO:** Debounce with `.task(id: searchText)` + `Task.sleep(for: .milliseconds(300))`.\n\n**DON'T:** Silently fail when location authorization is denied.\n**DO:** Detect `.denied` status and show an alert with a Settings deep link.\n\n**DON'T:** Assume geocoding always succeeds — handle empty results and network errors.\n\n## Review Checklist\n\n- [ ] Info.plist has `NSLocationWhenInUseUsageDescription` with specific reason\n- [ ] Authorization denial handled with Settings deep link\n- [ ] `CLLocationUpdate` task cancelled when not needed (battery)\n- [ ] Location accuracy appropriate for the use case\n- [ ] Map annotations use `Identifiable` data with stable IDs\n- [ ] Geocoding errors handled (network failure, no results)\n- [ ] Search completer input debounced\n- [ ] `CLMonitor` limited to 20 conditions, instance kept alive\n- [ ] Background location uses `CLBackgroundActivitySession`\n- [ ] Map tested with VoiceOver\n- [ ] Map annotation view models and location UI updates are `@MainActor`-isolated\n\n## References\n\n- [references/mapkit-patterns.md](references/mapkit-patterns.md) — Map setup, annotations, search, routes, clustering, Look Around, snapshots.\n- [references/mapkit-corelocation-patterns.md](references/mapkit-corelocation-patterns.md) — CLLocationUpdate, CLMonitor, CLServiceSession, background location, testing.","tags":["mapkit","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-mapkit","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/mapkit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.684","qualityRationale":"deterministic score 0.68 from registry signals: · indexed on github topic:agent-skills · 468 github stars · SKILL.md body (15,345 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:53:43.613Z","embedding":null,"createdAt":"2026-04-18T22:01:05.127Z","updatedAt":"2026-04-22T00:53:43.613Z","lastSeenAt":"2026-04-22T00:53:43.613Z","tsv":"'-122.009':492 '-122.0090':901 '0':918 '0.05':496,498 '0.15':449 '0.3':432 '1':132,140,187,234,276,453,878 '1000':525 '17':49,92,98,322,643,1335 '18':195,719,771 '2':143,183,192,240,285,436 '20':1492 '26':114,118,925,947,973,1216,1220,1252,1272 '3':152,202,230,251,292 '300':1406 '300ms':246 '37.334':490 '37.3349':899 '3d':513,560 '4':164,208,260,269,295,423 '5':170,219,302,1162 '50':704 '500':446 '6':176,401 '60':529 '8':863 '90':527 'access':833,841 'accuraci':214,701,750,796,1464 'action':848 'add':133,153,171,188 'address':870,913,942,976,986,1022,1057,1260 'addressstr':985 'alert':1423 'aliv':1496 'alway':792,807,1316,1433 'anchor':395 'angl':512 'annot':23,139,155,366,384,391,1471,1506,1521 'api':57,101,105,640 'app':12 'appl':345,879 'applepark':348,523 'appropri':1465 'area':425 'around':439,1526 'assum':1431 'async':56,650,952,978,1047,1084,1119,1191,1226,1279,1339 'author':201,721,747,755,793,797,810,1413,1449 'authorizedalway':1304 'autocomplet':238,995 'automat':336,509,1368 'automobil':288,1118 'avail':945,971,1218,1270 'await':293,688,707,876,905,967,991,1066,1102,1139,1174,1209,1246,1297 'awar':45 'background':402,1323,1497,1533 'balloon':368 'base':41 'batteri':1359,1462 'bind':151,182,462 'blue':421,1160 'blue.gradient':403 'bodi':338,827 'bottom':396 'broad':1308 'brown':383 'build':38 'building.2':353 'button':849 'cafe':377 'cafecoord':381 'calcul':1181 'callback':646 'camera':454,474,511,520 'cancel':714,1367,1458 'case':1469 'center':443,476,487 'centercoordin':522 'check':809 'checklist':125,128,311,1442 'circl':405,411,437 'class':666,999 'clbackgroundactivitysess':1500 'cleaner':1342 'clgeocod':861,867 'cllocat':660,672,897,951 'cllocationcoordinate2d':488,890,1278 'cllocationmanagerdeleg':645,1328 'cllocationupd':656,1456,1530 'cllocationupdate.liveupdates':64,204,641,685,772,1338 'clmonitor':69,774,1489,1531 'closur':163 'clplacemark':1376 'clservicesess':198,717,754,778,1532 'cluster':1524 'coalesc':1386 'code':306,1345 'common':119,122,1299 'common-mistak':121 'commonnam':1288 'compactmap':917 'complet':254,1014,1026,1031,1032,1045,1053,1054,1486 'completer.delegate':1019 'completer.queryfragment':1010 'completer.results':1029 'completer.resulttypes':1021 'completerdidupdateresult':1025 'concis':1344 'condit':1493 'configur':165,235 'contain':657 'content':85 'contentunavailableview':830 'continu':697,706 'control':173,457 'convert':252 'coordin':347,354,380,390,393,416,418,428,615,872,893,1165,1169,1258,1277,1286,1287 'coreloc':16,55,83,99,103,638,663 'corelocation-modern-api':102 'creat':144,196,277,783,786,1253 'cup.and.saucer.fill':379 'cupertino':882 'currentloc':671 'custom':385 'cycl':291,1213,1237 'data':936,1474 'debounc':241,1398,1488 'declar':720 'deep':1427,1454 'default':544,578 'deni':817,834,1415,1418 'denial':1450 'descript':837 'descriptor':1283,1294 'destin':283,1114,1128,1189,1200,1224,1235 'detect':1417 'didfailwitherror':1034 'didset':1009 'direct':33,110,111,271,1106,1132,1202,1214,1239 'directions.calculate':1140,1247 'directions.calculateeta':1210 'disappear':1370 'display':261,273,461,1143 'distanc':212,524 'distrust':1307 'done':768 'drain':1358 'draw':296 'elev':358,549,558,568 'els':633,696,705,961,987 'empti':1436 'enabl':839,1321 'end':314,1168 'endcoord':1170 'enditem':1179 'environ':821 'error':1035,1036,1440,1479 'escal':1314 'eta':1180 'everi':1395 'exist':304 'explicit':785,788 'extend':76 'fail':1410 'failur':1482 'fallback':508 'featur':9,46,725,847,1324 'fetch':1332 'figure.wave':399 'file':317 'filter':209,698 'final':665,998 'fire':1391 'flexibl':941 'flow':798 'follow':499 'forc':1374 'force-unwrap':1373 'foreach':609 'foregroundstyl':406,430,447 'format':943 'forward':868 'forwardgeocod':975 'frame':530 'full':258,749,795,1039 'fullaccuracypurposekey':757 'func':679,711,948,974,1024,1030,1042,1078,1108,1183,1221,1273 'geocod':29,31,106,107,860,866,869,892,930,1432,1478 'geocoder.geocodeaddressstring':877 'geocoder.reversegeocodelocation':906 'geofenc':36,71 'geotoolbox':1268 'get':270 'getcyclingdirect':1222 'getdirect':1109,1175 'geteta':1184 'green':434 'green.opacity':431 'guard':629,692,702,955,981 'guid':812 'handl':177,1435,1451,1480 'head':526 'highlight':426 'hold':728,759 'horizont':700 'hybrid':563,567 'id':1265,1401,1477 'identifi':1473 'imag':397 'imageri':554,557 'implement':2 'implicit':777 'import':141,324,326,662,1267 'improv':5 'infinit':350 'infiniteloop':355 'info.plist':191,800,1443 'init':1017 'input':243,1487 'insid':160 'instanc':1494 'interact':468,573,597 'io':48,91,97,113,117,194,321,642,718,770,862,924,946,972,1215,1219,1251,1271,1334 'ios/macos':11 'isol':1515 'item':532,534,631 'iter':203,653 'join':919 'keep':1348 'kept':1495 'key':801 'keystrok':1396 'label':565,831 'languag':1073 'latitud':489,898 'latitudedelta':495 'least':245 'let':465,630,683,693,752,853,865,873,884,895,902,909,912,956,964,982,1013,1050,1058,1063,1087,1094,1099,1122,1131,1136,1155,1194,1201,1206,1229,1238,1243,1282,1290 'lifetim':727 'limit':1490 'linewidth':422,435,452,1161 'link':1428,1455 'list':268 'locat':8,27,44,67,186,224,375,501,694,710,740,832,840,885,887,896,907,950,959,960,1331,1349,1412,1463,1498,1510,1534 'location-awar':43 'location.coordinate':889 'location.horizontalaccuracy':703 'location.slash':836 'locationpermissionview':819 'locationtrack':667 'long':736 'longer':228 'longitud':491,900 'longitudedelta':497 'look':1525 'lookupplac':1274 'loop':351 'mainactor':1514 'mainactor.run':708 'manag':200 'map':6,21,40,59,89,95,135,146,166,172,319,341,413,460,539,546,572,595,598,606,1146,1153,1470,1501,1505,1519 'map-bas':39 'map/location':305 'map/view':1354 'mapcamera':521 'mapcameraposit':150,335,456,484,506,519 'mapcircl':159,442 'mapcompass':362 'mapcontentbuild':61,162 'mapcontrol':175,360 'mapinteractionmod':576,583,587,593 'mapitem':965 'mapitems.first':970 'mapkit':1,14,37,52,77,142,325,928 'mapkit-n':927 'mappolygon':157,427 'mappolylin':156,300,417,1157 'mapscaleview':363 'mapstyl':169,356,542,547,553,556,562,566 'mapuserlocationbutton':361 'marker':24,137,154,264,344,349,364,369,376,613,1163,1167 'match':621 'millisecond':1405 'mistak':120,123,1300 'mkaddress':938 'mkaddressrepresent':939 'mkcoordinateregion':486,1083 'mkcoordinatespan':494 'mkdirect':1133,1203,1240 'mkdirections.calculate':294 'mkdirections.request':279,1124,1196,1231 'mkdirectionstransporttyp':1117 'mkgeocodingrequest':921,984 'mklocalsearch':1038,1060,1096 'mklocalsearch.request':256,1052,1089 'mklocalsearchcomplet':236,994,1005,1015,1027,1033,1046,1392 'mklocalsearchcompleterdeleg':1002 'mkmapitem':284,605,933,954,980,1049,1086,1112,1115,1187,1190,1225,1281 'mkmapitem.forcurrentlocation':535,1233 'mkmapitemrequest':1292 'mkmaprect':538 'mkreversegeocodingrequest':923,958 'mkrout':1121,1152,1228 'mode':574 'model':1508 'modern':54,100,104,639 'move':472 'must':620 'name':1275,1289 'nativ':929 'natur':1072 'nearbysearchpurpos':758 'need':229,739,791,808,1262,1461 'network':1439,1481 'never':678 'new':926 'newvalu':627,632 'nil':716,963,1385 'nil-coalesc':1384 'nslocationalwaysandwheninuseusagedescript':804 'nslocationwheninuseusagedescript':189,803,1445 'nsobject':1001 'observ':664,997 'onchang':624 'one':784,787 'open':850 'openurl':822,825,858 'option':149,659,1381 'overlay':408 'overrid':1016 'pad':400 'pan':579,584,585,588,590 'park':346,880 'parkboundari':429 'pattern':78,84 'permiss':1309 'perspect':514 'pin':373 'pitch':528,582 'place':233,610,611,1255,1264 'place.coordinate':616 'place.mapitem':618 'place.name':614 'placedescriptor':112,116,1250,1284,1293 'placedescriptor-io':115 'placemap':329 'placemark':874,894,903,910 'placemark.administrativearea':916 'placemark.locality':915,1387 'placemark.name':914 'placemarks.first':886,911 'point':441 'pointofinterest':1023,1056 'polygon':410,424 'polylin':25,409,414 'posit':334,342,343,455,483,505,518,533,536 'prefer':751 'print':888 'privat':332,481,503,516,602,673,823,1012,1149 'programmat':471 'properti':764,1377 'queri':250,1007,1011,1074,1080,1091,1393 'radius':438,445 'react':635 'realist':359,550,559,569 'reason':1448 'rect':537 'red':451 'red.opacity':448 'refer':129,130,730,1256,1516 'references/mapkit-corelocation-patterns.md':80,81,1528,1529 'references/mapkit-patterns.md':73,74,1517,1518 'region':479,485,1077,1082,1093 'releas':765 'replac':644 'represent':1285 'request':957,983,1051,1061,1062,1088,1097,1098,1123,1134,1135,1195,1204,1205,1230,1241,1242,1291,1303 'request.destination':1127,1199,1234 'request.mapitem':1298 'request.mapitems':968,992 'request.naturallanguagequery':1090 'request.region':1092 'request.resulttypes':1055 'request.source':1125,1197,1232 'request.transporttype':1129,1236 'requestwheninuseauthor':1313 'requir':722,802,1266 'respons':1064,1100,1137,1207,1244 'response.expectedtraveltime':1212 'response.mapitems':1069,1105 'response.routes.first':1142,1249 'result':259,262,1004,1028,1037,1437,1484 'return':634,932,962,969,988,989,1068,1104,1141,1211,1248,1295 'revers':30,891 'reversegeocod':949 'review':3,124,127,303,310,1441 'review-checklist':126 'rich':1254 'richer':935 'road':545 'rotat':581 'rout':35,275,298,1144,1151,1156,1172,1523 'route.polyline':301,1158 'routecoord':419 'run':307,1351 'satellit':555,561,564 'search':108,109,231,993,1040,1043,1059,1070,1095,1485,1522 'search.start':1067,1103 'search/autocomplete':32 'searchcomplet':1000 'searchnearbi':1079 'searchtext':1402 'see':72 'select':178,181,253,599,607,622,637 'selectedmark':604,608,626 'self':1020 'self.currentlocation':709 'sendabl':669 'separ':920 'sequenc':651 'servic':741 'session':733,753,760 'set':248,286,815,843,851,1426,1453 'setup':1520 'show':1421 'showstraff':551,570 'silent':1409 'simpl':1330 'simplest':370 'singl':649 'skill' 'skill-mapkit' 'snapshot':1527 'sourc':281,1111,1126,1186,1198 'source-dpearson2699' 'span':493 'specif':510,531,1447 'stabl':1476 'standard':357,543,548 'start':1164,1311 'startcoord':1166 'startitem':1177 'starttrack':680 'state':331,480,502,515,601,1148 'static':594 'status':1419 'stop':220 'stoptrack':712 'store':763 'storecoord':444 'stream':66,1340 'string':856,871,977,1008,1081,1276 'stroke':420,433,450,1159 'struct':328,818 'style':167,540 'succeed':1434 'suggest':239 'super.init':1018 'swift':323,367,412,475,541,575,600,661,742,799,864,944,996,1041,1107,1147,1182,1217,1269 'swiftui':51,88,94,318,327,386,1364 'swiftui-map-view-io':93 'systemimag':352,378,835 'systemnam':398 'tag':617,619 'take':775 'target':47 'task':207,222,676,682,1171,1362,1400,1457 'task.sleep':1403 'test':1502,1535 'text':838 'throw':953,979,1048,1085,1120,1192,1227,1280 'timeinterv':1193 'tint':382 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'track':28,184,225 'transit':290 'transport':1116,1130 'transporttyp':287 'tri':687,875,904,966,990,1065,1101,1138,1173,1208,1245,1296 'true':552,571 'type':623 'ui':218,1511 'uiapplication.opensettingsurlstring':857 'uncheck':668 'unknown':1388 'unwrap':1375 'updat':210,216,684,689,691,1350,1366,1512 'update.location':695 'updatetask':675,681,713,715 'upfront':1305 'url':854,855,859 'use':13,17,58,746,845,1327,1337,1361,1383,1468,1472,1499 'user':26,185,242,467,500,813,1306,1320 'usercoord':394 'userloc':507 'var':333,337,482,504,517,603,670,674,824,826,1003,1006,1150 'view':22,63,90,96,147,320,330,340,387,820,829,1507 'visibl':1357 'voiceov':1504 'void':677 'walk':289 'way':371,881 'when-in-us':743 'wheninus':756 'white':407 'within':1075 'without':1261 'work':19 'workflow':86,87,131 'yield':654 'zoom':580,589,592","prices":[{"id":"947d826c-f0f7-4c77-bcc4-4d4973d5bf1b","listingId":"d49d7900-4974-4b94-b62f-766331f887a1","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:01:05.127Z"}],"sources":[{"listingId":"d49d7900-4974-4b94-b62f-766331f887a1","source":"github","sourceId":"dpearson2699/swift-ios-skills/mapkit","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/mapkit","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:05.127Z","lastSeenAt":"2026-04-22T00:53:43.613Z"}],"details":{"listingId":"d49d7900-4974-4b94-b62f-766331f887a1","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"mapkit","github":{"repo":"dpearson2699/swift-ios-skills","stars":468,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-21T19:26:16Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"b31203c019a2647fabd06d855f73a5334a81d391","skill_md_path":"skills/mapkit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/mapkit"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"mapkit","description":"Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, annotations, markers, polylines, user location tracking, geocoding, reverse geocoding, search/autocomplete, directions and routes, geofencing, region monitoring, CLLocationUpdate async streams, or location authorization flows. Also use when working with maps, coordinates, addresses, places, directions, distance calculations, or location-based features in Swift apps."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/mapkit"},"updatedAt":"2026-04-22T00:53:43.613Z"}}