Maps & Location

RSS for tag

Learn how to integrate MapKit and Core Location to unlock the power of location-based features in your app.

Maps & Location Documentation

Post

Replies

Boosts

Views

Activity

Map In TabView
In SwitUI when using a map within a tabview the tab bar color is translucent when the map tab is selected. All of the other tabs the tab bar is opaque. In the view that contains the map, if the map is commented out the tab display is opaque, only when the map is displayed. I have an init in the tabview to set the tab bar parameters: // Set Tab Bar appearance let tabbarAppearance = UITabBarAppearance() tabbarAppearance.configureWithOpaqueBackground() tabbarAppearance.backgroundColor = .blue UITabBar.appearance().standardAppearance = tabbarAppearance UITabBar.appearance().scrollEdgeAppearance = tabbarAppearance In the view with the map I use a ZStack to set the entire screen color: ZStack(alignment: Alignment(horizontal: .center, vertical: .top)) { Color(.blue) .ignoresSafeArea(.all) .foregroundColor(.black) VStack(alignment: .center, spacing: 5) { Spacer() Map() Spacer() } } I've tried using .padding(), frame, removing ignoresSafeArea but the tab bar still becomes translucent when the tab is selected. Selecting another tab the color becomes opaque. Any suggestions on how to correct this behavior so the tab bar is opaque for all tabs?
0
0
455
Jan ’24
Maps searchAutoComplete response field "structuredAddress" always null
Regardless of how much information is provided to the Maps searchAutoComplete API, the response field structuredAddress is always null. This means I have to call the completionUrl afterwards to get a structured address. This consumes our quota and causes unnecessary Maps traffic. Example request, autocompleting "450 Post St, San Francisco": https://maps-api.apple.com/v1/searchAutocomplete? q=450%20Post%20St%2C%20San%20Francisco &resultTypeFilter=Address &limitToCountries=US &lang=en-US responds 2 results with the actual address found, but each having only these fields: - completionUrl - displayLines - location Example: { "results": [ { "completionUrl": "/v1/search?q=450%20Post%20St%20San%20Francisco%2C%20CA%2C%20United%20States&metadata=Ch8KCzQ1MCBQb3N0IFN0EgQIABADEgQIBBAEEgQICRACEjQKIFNhbiBGcmFuY2lzY28sIENBLCBVbml0ZWQgU3RhdGVzEgQIGhACEgQIABADEgQIBBAJGAIyRgoSCQAAAEDg5EJAEQAAAOA9ml7AEM6h0aK1wfKqciA5KQAAAAAAAHlAgvEEAzQ1MIjxBDGa8QQCVVOg8QQAsvEEALrxBABiHAoaNDUwIFBvc3QgU3QsIFNhbiBGcmFuY2lzY2%2BC8QQaNDUwIFBvc3QgU3QsIFNhbiBGcmFuY2lzY2%2BI8QQA2vEEFgkAAABAEf3IQBkAAAAAAAAAACABKAPq8QQAkPIEAQ%3D%3D", "displayLines": [ "450 Post St", "San Francisco, CA, United States" ], "location": { "latitude": 37.78809356689453, "longitude": -122.41002655029297 } }, { "completionUrl": "/v1/search?q=450%20Post%20St%20Napa%2C%20CA%2C%20United%20States&metadata=****", "displayLines": [ "450 Post St", "Napa, CA, United States" ], "location": { "latitude": 38.30093002319336, "longitude": -122.27799224853516 } } ] } Anyone figured this out? Seems buggy to me.
0
2
703
Jan ’24
Is it free to use MapKit's MKLocalSearchCompleter and MKLocalSearch on iOS currently?
Is it free to use MapKit's MKLocalSearchCompleter and MKLocalSearch on iOS currently? I would like to use them for getting geocode. I found this forum. https://developer.apple.com/forums/thread/127493 According to this forum, using MapKit for native app development, there is no cost beyond my Apple Developer Program membership. Is it the same now? sincerely
0
0
535
Jan ’24
How to select MapFeature by custom type
If have a custom type (hashable) for map selection: @State var mapSelection: CustomType Map(selection: $mapSelection ) { ... } However, if I want to selet MapFeature, I need to use MapFeature type for the state variable @State var mapSelection: MapFeature But I want to display some Markers by using my CustomType. MapFeature can't be initialized so that I can't map my CustomType to MapFeature to display my Markers. Is there a way to select MapFeature by custom type?
1
1
412
Jan ’24
Searching for an example of a proper iBeacon implementation for iOS 17
Hello, I'm looking for an end-to-end example project that shows a correct implementation for the new iBeacon CoreLocation APIs in iOS 17.0 (CLMonitor, etc.). Ideally the example would cover background waking as that is the area in which I am facing the largest challenges. Perhaps there's an Open Source project or an official Apple example? Thanks for pointing me in the right direction. Jeremy
3
0
1.1k
Jan ’24
Region monitoring not working after 1 hour the app is killed.
This is my setup: Granted always allow permission. I have location added in UIBackgroundModes, but I did NOT set allowsBackgroundLocationUpdates to true Note: I have this allowsBackgroundLocationUpdates = true set in my earlier version of app, which worked but we noticed it drained battery much faster, hence we removed all the settings that could affect battery. The location model is setup with 20 regions, when boundary crossing happen, app sends a local notification. This works fine when app is in foreground/background. If app is killed, the app receives notification for boundary crossing only once. Failed case for region monitoring: Setup region monitoring Kill the app cross the boundary, app sends a local notification. wait for 1 hour leave the device in same state (notification is not opened, app is still killed state) cross the boundary again expect a notification, but app did not register any event related to region monitoring. The console logs did not print anything in this second case. public class LocationViewModel: NSObject, ObservableObject { private let maxMonitoredRegions = 20 private var anyCancellable: AnyCancellable? private let locationManager: CLLocationManager @Published public var authorizationStatus: CLAuthorizationStatus @Published public var isMonitoringAvailable: Bool @Published public var monitoredRegions: [Region] @Published public var recentLocation: CLLocation? public var newlyEnteredRegionSignal = PassthroughSubject<CLRegion, Never>() public var recentLocationSignal = PassthroughSubject<CLLocation, Never>() public var authorizationStatusPublisher: Published<CLAuthorizationStatus>.Publisher { $authorizationStatus } public var isLocationEnabled: Bool { locationManager.authorizationStatus == .authorizedWhenInUse || locationManager.authorizationStatus == .authorizedAlways } public override init() { locationManager = CLLocationManager() authorizationStatus = locationManager.authorizationStatus isMonitoringAvailable = CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) monitoredRegions = [] super.init() locationManager.delegate = self monitoredRegions.append(contentsOf: getMonitoredRegions()) requestLocation() } public func requestLocation() { locationManager.requestLocation() } public func startRegionMonitoring(regions: [CLRegion]) { guard isMonitoringAvailable else { return } stopRegionMonitoring() if regions.isEmpty { return } if regions.count <= 20 { for region in regions { locationManager.startMonitoring(for: region) } } else { for region in regions[0...maxMonitoredRegions-1] { locationManager.startMonitoring(for: region) } } } public func stopRegionMonitoring() { guard isMonitoringAvailable else { return } if monitoredRegions.isEmpty { return } for region in monitoredRegions { let monitoredRegion = LocationUtils.convertRegionToCLRegion(region) locationManager.stopMonitoring(for: monitoredRegion) } monitoredRegions.removeAll() } private func getMonitoredRegions() -> [Region] { let monitoredRegions = locationManager.monitoredRegions var regions = [Region]() for monitoredRegion in monitoredRegions { if let region = LocationUtils.convertCLRegionToRegion(monitoredRegion) { regions.append(region) } } return regions } public func stopMonitoring() { recentLocation = nil stopRegionMonitoring() } } extension LocationViewModel: CLLocationManagerDelegate { public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { authorizationStatus = manager.authorizationStatus switch authorizationStatus { case .notDetermined: stopMonitoring() case .denied: stopMonitoring() case .authorizedAlways: break case .authorizedWhenInUse: // If user has requested whenInUse, request for always allow. locationManager.requestAlwaysAuthorization() @unknown default: break } if let location = manager.location { recentLocationSignal.send(location) recentLocation = location } } public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let recentLocation = locations.last { self.recentLocation = recentLocation recentLocationSignal.send(recentLocation) } } public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { } public func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) { if let monitoredRegion = LocationUtils.convertCLRegionToRegion(region) { let oldRegion = monitoredRegions.first { $0.identifier == monitoredRegion.identifier } if oldRegion == nil { monitoredRegions.append(monitoredRegion) } } } public func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) { } public func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) { newlyEnteredRegionSignal.send(region) } public func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) { newlyEnteredRegionSignal.send(region) } } When app is awaken due to location event on app delegate, we initialize this location model, and location manager, and remove old monitored regions, and call startMonitoringRegions again, to keep the regions updated. Please let me know if I'm missing any crucial information.
1
1
487
Jan ’24
Asking Location Permission is not working on the AppIntents
@MainActor perform() async throws -> some IntentResult { // ... switch locationManager.authorizationStatus { case .denied, .restricted: throw UserLocationError.permissionDenied case .notDetermined: await locationManager.requestWhenInUseAuthorization() // to ask permission default: break } // ... } Here is my code. When the authorizationStatus is .notDetermined, it invokes requestWhenInUseAuthorization() method on the main thread, but throws UserLocationError.permissionDenied immediately, eventhough I didn't deny the permission. It's really weird and unexpected that it throws UserLocationError.permissionDenied when the status is not .denied or .restricted Even it invokes requestWhenInUseAuthorization(), there's no alert for asking permission If there's any solution, please let me know
0
0
465
Jan ’24
MapView mapType `.standard` iOS17 does not allow 3d
I am working on a virtual simulator for iOS 17 from my macbook. I want to have the initial view present the Map but zoomed out enough so that it's basically showing the whole world - in a 3d render. My understanding is that as of iOS17 if you have .standard for the MKMapView type, it should still render as 3D if the altitude is high enough. But on my simulator, I literally cannot zoom out any further. Is the right protocol to update the mapType to be .hybridFlyover? That seems different than the .standard (which I think is what I actually want). Does anyone have any idea / is there anything sticking out in this code? Here is my code: struct GlobeView: UIViewRepresentable { var coordinates: [IdentifiableCoordinate] func makeUIView(context: Context) -> MKMapView { let mapView = MKMapView() mapView.mapType = .hybridFlyover mapView.delegate = context.coordinator let camera = MKMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 0, longitude: 0), fromDistance: 1_000_000_000, pitch: 0, heading: 0) mapView.setCamera(camera, animated: true) return mapView } func updateUIView(_ uiView: MKMapView, context: Context) { let annotations = coordinates.map { coordinate -> MKPointAnnotation in let annotation = MKPointAnnotation() annotation.coordinate = coordinate.coordinate return annotation } uiView.addAnnotations(annotations) } class Coordinator: NSObject, MKMapViewDelegate { var parent: GlobeView init(_ parent: GlobeView) { self.parent = parent } } func makeCoordinator() -> Coordinator { Coordinator(self) } }
1
0
469
Jan ’24
Join in Apple Developer and Find My Network as a Chinese College Student
Hi, I'm a college student in Hangzhou, China. I want to learn and develop with Find My Network and other useful Apple's tech. But when I access the application website, I can't find the university entrance but only with company. Can I develop as a college student? Where can I be? Or in the same page, what's the DUNS numbers? If only corps can, what's the fee to get the DUNS numbers with Apple's support? What's the fee to join in Apple Developments? Should I offer some documents such as Bank Corporate Account Statement? If I create a new corp to join in the development, what should I or corp need and do? I just wanna develop a school ID card with UWB tech and Apple's useful Find My Network. Hope to get your's help. Have a good day. Thanks!
0
0
497
Jan ’24
MapKit top MKTileOverlay blendMode overrides lower MKTileOverlay blendMode
I need multiple MKTileOverlays with multiple blendModes. Apparently using an overlay with a different blend causes the layer under to use the same blend mode. For the example below, using a normal blend mode on top of a soft light blend mode causes a normal blend mode to be used instead of soft light. The soft light layer is rendered as expected until the normal layer is displayed starting at zoom level 15. First, I've subclassed MKTileOverlay to add an overlay type so that the correct renderer is provided per overlay. (I know there is a title, but I prefer this) enum OverlayType { case softLight, normal } class TileOverlay: MKTileOverlay { var type: OverlayType = .normal } Then setup layers and renderers in the typical fashion: var softLightRenderer: MKTileOverlayRenderer! var normalRenderer: MKTileOverlayRenderer! private func setupSoftlightRenderer() { let overlay = TileOverlay(urlTemplate: "http://localhost/softlight/{z}/{x}/{y}") overlay.type = .softLight overlay.canReplaceMapContent = false overlay.minimumZ = 9 overlay.maximumZ = 20 mapView.addOverlay(overlay, level: .aboveLabels) softLightRenderer = MKTileOverlayRenderer(tileOverlay: overlay) tileRenderer.blendMode = .softLight } private func setupNormalRenderer() { let overlay = TileOverlay(urlTemplate: "http://localhost/normal/{z}/{x}/{y}") overlay.type = .normal overlay.canReplaceMapContent = false overlay.minimumZ = 15 overlay.maximumZ = 20 mapView.addOverlay(overlay, level: .aboveLabels) normalRenderer = MKTileOverlayRenderer(tileOverlay: overlay) normalRenderer.blendMode = .normal } func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { if let overlay = overlay as? TileOverlay { switch overlay.type { case .softLight: return softLightRenderer case .normal: return normalRenderer } } print("Warning: using unhandled overlay renderer") return blankRenderer } override func viewDidLoad() { ... setupSoftlightRenderer() setupNormalRenderer() } Interestingly, if I put the overlays at two different levels, one .aboveLabels and another .aboveRoads it works as expected. The problem is that limits me to two different overlay blend modes. I really could use more than two. I tried every possible variation of inserting the layers at different indexes and methods, but the only two that seem to work are the .aboveLabels and .aboveRoads. How can I use more than two different blend modes?
1
0
493
Jan ’24
how to get user live location in Background and terminated mode?
Hi All, I need user continues location event if app in background and terminated (Not-running) mode below is the code I'm using to get the location but still I'm not get the location continuously import BackgroundTasks import UIKit class AppDelegate: UIResponder, UIApplicationDelegate { var significatLocationManager: CLLocationManager? func startSignificationLocation() { self.significatLocationManager = CLLocationManager() self.significatLocationManager?.delegate = self self.significatLocationManager?.activityType = .fitness self.significatLocationManager?.distanceFilter = 10 self.significatLocationManager?.desiredAccuracy = kCLLocationAccuracyNearestTenMeters self.significatLocationManager?.allowsBackgroundLocationUpdates = true self.significatLocationManager?.pausesLocationUpdatesAutomatically = false self.significatLocationManager?.startUpdatingLocation() self.significatLocationManager?.startMonitoringSignificantLocationChanges() self.significatLocationManager?.requestAlwaysAuthorization() } func stopAllRegionMonitoring(locationManager:CLLocationManager?){ for delRegion in (locationManager?.monitoredRegions ?? []){locationManager?.stopMonitoring(for: delRegion)} } } extension AppDelegate: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { self.myLocation = locations.last //call update My Location API if (self.myLocation?.horizontalAccuracy ?? 0.0) <= (self.liveLocationTrackingRegionRadius + 15.0 ){ self.createRegion(location: self.myLocation) } else { manager.stopUpdatingLocation() manager.startUpdatingLocation() } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {} func locationManagerDidPauseLocationUpdates(_ manager: CLLocationManager) { manager.startUpdatingLocation() } func locationManagerDidResumeLocationUpdates(_ manager: CLLocationManager) { manager.startUpdatingLocation() } } extension AppDelegate { func createRegion(location:CLLocation?, type:LocationRegionMonitoringTyep = .LiveLocationTracking) { if self.significatLocationManager == nil { self.startSignificationLocation() } guard let location = location else { return } guard CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) else{ return } var identifier:String = "Live_Location_Tracking-" + "\(location.coordinate.latitude)" + "-" + "\(location.coordinate.longitude)" if (self.significatLocationManager?.monitoredRegions.count ?? 0) > 10 { self.stopAllRegionMonitoring(locationManager: self.significatLocationManager) } var region : CLCircularRegion? region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: location.coordinate.latitude,longitude: location.coordinate.longitude),radius: 10.0 ,identifier: identifier) region?.notifyOnExit = true self.significatLocationManager?.startUpdatingLocation() if let reg = region { self.significatLocationManager?.startMonitoring(for: reg) } } func stopAllRegionMonitoring(locationManager:CLLocationManager?){ let WOMRequestId:String? = UserDefaultManager.shared.womEmergencyDetails?.data?.request?.id for delRegion in (locationManager?.monitoredRegions ?? []){ if let reqId = WOMRequestId { if delRegion.identifier.contains(reqId) { locationManager?.stopMonitoring(for: delRegion) } } else { locationManager?.stopMonitoring(for: delRegion) } } } func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) { if region.identifier.contains(AppConstants.WatchOverMe) { AppDelegate.shared?.isWOMReachDestination(location: manager.location, region: region) } } func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) { self.myLocation = manager.location manager.stopMonitoring(for: region) self.significatLocationManager?.stopMonitoring(for: region) manager.startUpdatingLocation() self.significatLocationManager?.startUpdatingLocation() self.createRegion(location: self.myLocation) //update M yLocation API if region.identifier.contains( AppConstants.WatchOverMe ) { TabBarController.isWOMReachDestinationAlertShown = false } } func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) { self.myLocation = manager.location self.createRegion(location: self.myLocation) } } extension AppDelegate { func applicationDidEnterBackground(_ application: UIApplication) { self.scheduleBackgroundTask() } func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { completionHandler(.newData) } func registerBGTask(){ BGTaskScheduler.shared.register(forTaskWithIdentifier: self.getBGTaskIdentifier(), using: nil) { task in self.handleBackgroundTask(task: task as! BGAppRefreshTask) } } func handleBackgroundTask(task: BGAppRefreshTask) { task.setTaskCompleted(success: true) } func scheduleBackgroundTask() { let request = BGAppRefreshTaskRequest(identifier: self.getBGTaskIdentifier() ) request.earliestBeginDate = Date(timeIntervalSinceNow: 10) // 30 second do { try BGTaskScheduler.shared.submit(request) } catch { print("Unable to schedule background task: (error)") } } func getBGTaskIdentifier()->String { let bundleId:String = AppInfoManager.shared.bundleId + ".locationBackgroundTask" return bundleId } func startLocationTrackingTimer() { self.stopLocationTrackingTimer() self.locationTrackingTimer = Timer.scheduledTimer(timeInterval: 1.0,target: self, selector: #selector(self.updateUserLocation),userInfo: nil,repeats: true) RunLoop.current.add(self.locationTrackingTimer!, forMode: .common) } func stopLocationTrackingTimer() { self.locationTrackingTimer?.invalidate() self.locationTrackingTimer = nil } @objc func updateUserLocation() { if self.isSocketActive { self.updateMyLocationAPI(fromRoam: false) } else { self.updateUserCurrentLocation() } } }
0
0
484
Jan ’24
CLLocationManagerDelegate Bug on VIsionOS
I found something when I use CLLocationManagerDelegate on VisionOS. When I called func locationManagerDidChangeAuthorization func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { switch manager.authorizationStatus { case .notDetermined, .denied: locationManager.requestWhenInUseAuthorization() default: locationManager.startUpdatingLocation() guard let center = locationManager.location?.coordinate else { return } isFollowing = false mapCamera = .region(.init(center: center, span: .init(latitudeDelta: 0.005, longitudeDelta: 0.005))) addItems() } } Although I choose allow auth, locationManagerDidChangeAuthorization wasn't called.
0
0
343
Feb ’24
Cannot select my created MKMapItem on the Map
Hi, I am learning about MapKit for SwiftUI, at first I created the MKMapItem @State private var mapSelection: MKMapItem? @State var starbucksReserve = MKMapItem(placemark: .init(coordinate: CLLocationCoordinate2D(latitude: 41.894178596474575, longitude: -87.62451598445733)))` I put that in the Map Map(position: $cameraPosition,selection: $mapSelection){ Marker("Starbucks Reserve", systemImage: "cup.and.saucer.fill" ,coordinate: starbucksReserve.placemark.coordinate) } Even though I have put the selection $mapSelection, my Marker is not selectable. I am not sure why. I tried to fix it by changing mapSelection to Int? and made a tag for Marker, but because I am learning how to use it so I want to make sure why marker cannot be selectable with the first approach? Thank you
0
0
387
Feb ’24
CLMonitor is Not Working and No way to debug!
CLMonitor WWDC video, it says the same name can be reused await CLMonitor("greeting") but the production iOS 17 API actually crashes. Is this the correct behaviour? (See screenshot 1) for try await events in monitor.events should work in from the WWDC video, but the production iOS 17 API does not work and need to insert await after in keyword. Also, never received any events from the monitor (See screenshot 2) WWDC Video: https://developer.apple.com/wwdc23/10147
0
4
628
Feb ’24
geolocation represented on 3d model
Hi Developers. I need to try to embed GeoData into a USDZ model and then have the capabilities to "explore" the model while walking around in the real world. e.g. load and display a 3D model of Time Square and show a location pin which displays a users' virtual position on the model... when the user walks 10 meters north, in the real world, the location pin must move 10m (to scale) on the displayed model. As a new developer, I'm starting from scratch so would benefit greatly from having my hand held - please don't be afraid of patronizing me. Step 1 - load and display the 3D model Step 2 - geolocate the user Step 3 - translate the user's current position into a position on the 3D model and represent their "position" on the model with a traditional GPS location marker "pin". Step 4 - move the user's GPS pin on the mode, relative to (and reflecting) their actual real world movement. Is this acheivable or have I explained things to ambiguously? I look forward to hearing from my savior(s) as soon as convenient. Thank you in advance
0
0
365
Feb ’24