In the apple map of some areas, there will be a very realistic real-life 3D map. And now I want to call it through 3d in visionOS (like model3d). How can I call it?
Note: What I ask for is not to have an effect similar to 3d on a flat screen like in iOS, but to display the USDZ model in visionOS.
MapKit
RSS for tagDisplay map or satellite imagery from your app's interface, call out points of interest, and determine placemark information for map coordinates using MapKit.
Posts under MapKit tag
143 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
const lookup = new mapkit.PlaceLookup()
lookup.getPlace(input?.id, (error, place) => {
console.log("place", place)
...
gives me for example
{
"id": "I65A54A72CE9E45D6",
"alternateIds": [
"IB86C41DA005E0D9B"
],
"muid": "7324342225941186006",
"_styleAttributes": "4:226,6:16,10:0,82:12,85:12,89:1,164:1,193:1",
"name": "The Museum of Modern Art",
"region": {
"center": {
"latitude": 40.7612829,
"longitude": -73.9768677
},
"span": {
"latitudeDelta": 0.008983199999995861,
"longitudeDelta": 0.01186000000001286
}
},
"coordinate": {
"latitude": 40.7617238,
"longitude": -73.9777654
},
"formattedAddress": "11 W 53rd St, New York, NY 10019, United States",
"countryCode": "US",
"telephone": "+12127089400",
"urls": [
"http://www.moma.org"
],
"country": "United States",
"administrativeArea": "New York",
"administrativeAreaCode": "NY",
"locality": "New York",
"postCode": "10019",
"subLocality": "Manhattan",
"thoroughfare": "W 53rd St",
"subThoroughfare": "11",
"fullThoroughfare": "11 W 53rd St",
"areasOfInterest": [
"Manhattan"
],
"dependentLocalities": [
"Midtown Center",
"Midtown East",
"Midtown Manhattan",
"Midtown",
"North Hudson"
],
"timezone": "America/New_York",
"timezoneSecondsFromGmt": -14400
}
Note there is no pointOfInterestCategory. but
const place_search = new mapkit.Search()
place_search.search(
input,
(error, result) => {
console.log("result_places_0", result?.places?.[0])
...
i get
{
"id": "I65A54A72CE9E45D6",
"alternateIds": [
"IB86C41DA005E0D9B"
],
"muid": "7324342225941186006",
"_wpURL": "https://maps.apple.com/place?q=The%20Museum%20of%20Modern%20Art&auid=7324342225941186006&address=11%20W%2053rd%20St,%20New%20York,%20NY%20%2010019,%20United%20States&ll=40.7617238,-73.9777654",
"_styleAttributes": "4:226,6:16,10:0,82:12,85:12,89:1,164:1,193:1",
"pointOfInterestCategory": "Museum",
"name": "The Museum of Modern Art",
"region": {
"center": {
"latitude": 40.7612829,
"longitude": -73.9768677
},
"span": {
"latitudeDelta": 0.008983199999995861,
"longitudeDelta": 0.01186000000001286
}
},
"coordinate": {
"latitude": 40.7617238,
"longitude": -73.9777654
},
"formattedAddress": "11 W 53rd St, New York, NY 10019, United States",
"countryCode": "US",
"telephone": "+12127089400",
"urls": [
"http://www.moma.org"
],
"country": "United States",
"administrativeArea": "New York",
"administrativeAreaCode": "NY",
"locality": "New York",
"postCode": "10019",
"subLocality": "Manhattan",
"thoroughfare": "W 53rd St",
"subThoroughfare": "11",
"fullThoroughfare": "11 W 53rd St",
"areasOfInterest": [
"Manhattan"
],
"dependentLocalities": [
"Midtown Center",
"Midtown East",
"Midtown Manhattan",
"Midtown",
"North Hudson"
],
"timezone": "America/New_York",
"timezoneSecondsFromGmt": -14400
}
which gives me "pointOfInterestCategory": "Museum"
I think pointOfInterestCategory should also be returned in the placeLookup and might be a mapkit error that its not
it would also be cool if search autocomplete gave me the poi so i could tag the search result previews (mapbox does this).
Unrelated from this topic but coming from mapbox where everything had a mapbox_id i feel like some things like localities like "columbus, Ohio" should still have a place id but maybe the muid serves that purpose idk and just something i should account for.
Lastly on my mind is how to manage rate limiting since im just giving the same mapbox js token to all the clients. Of course for server api I can manage my own system for rate limiting logged in users a bit easier but not sure about mapkit js though I can only dream my project is big enough i need to even worry about that lol.
Hi ,
I have following scenario where I feel performance issue.
Use-case:
I have multiple Overlays(MKOverlay) rendered on MapView, and overlay needs to refresh on point Drag(MKPinAnnotation). I have custom logic to handle drag behaviour of annotation, on annotation drag I do update the overlay. As point update, I create new overlay with updated coordinate and re-render it. iT slow down the performance after few overlay added.
Additional Notes: Performance was quite good on iOS16 but on iOS17, it lags the perforce on point drag. When I say it the performance, it point drag lags so it slow the overlay rendering.
I am using MKMapView inside SwiftUI.
I am sharing code-snippet where it re-render the overlay. Please help with issue in my code implementation.
func renderSegments(mapView: MKMapView, segmentPoint: FencePointAnnotation, renderNeeded: Bool = true) {
mapViewModel.updateFencePointOrder()
guard let activeLayer = mapViewModel.activeLayer else {
debugPrint("Invalid active layer.")
return
}
let segments = mapViewModel.activeFence.connectedSegmentsOf(vertex: segmentPoint)
// Remove existing overlay.
for overlay in mapView.overlays {
if let overlay = overlay as? FenceOverlay {
if overlay.layerId == activeLayer.layerId {
mapView.removeOverlay(overlay)
}
} else if let overlay = overlay as? FenceSegmentPolyline {
if overlay.layerId == activeLayer.layerId {
for segment in segments.values where segment.identifier == overlay.identifier {
mapView.removeOverlay(overlay)
}
}
}
}
// When vertex removed the no need to add segment
if renderNeeded {
if let segments = mapViewModel.updatedSegements(segment: segments.map({$0.key})) {
let updatedSegments = mapView.updatedSegmentsWithOffset(segments: segments, layer: activeLayer)
mapView.addOverlays(updatedSegments)
}
}
}
Hi, I have a SwiftUI Map with a set of three annotations. These annotations move around, and I would like to animate their movement from one coordinate to another, but I'm not finding a way to do that.
I've tried using withAnimation { } when setting my array of Identifiable models that back the Annotations, and I've tried adding the .animation(.default, annotationModels) modifier to my Map object (where annotationModels is the array that backs my Annotations).
The animation modifier doesn't work on Annotation structs, and it doesn't work if I add the animation modifier within the Annotation's view either.
Does anyone have any suggestions on how I might be able to animate the coordinates of annotations using a SwiftUI Map? Does the problem have to do with the fact that I have an array of these annotations?
when I click on a mapview pin, a PopupView comes up with some text and a button. I want to be able to navigate to another DetailsView by clicking on the button display in the popup, the button is embedded inside NavigationLink. But clicking on the button nothing happens. How to navigate from button click?
struct MyMapView: View {
@State var position: MapCameraPosition = .automatic
@State var showCallout: Bool = false
@State var selected: PinAnnotation?
@Binding var locationPins: [PinAnnotation]
@State private var toggler = false
var body: some View {
Map(position: $position) {
ForEach(locationPins, id: \.self) { result in
Annotation(result.title!, coordinate: result.coordinate) {
ZStack {
Image(systemName: "mappin.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
.onTapGesture {
selected = result
toggler.toggle()
}
.foregroundStyle(.white, .purple)
if selected == result && toggler {
PopupView(pin: selected)
} else {
EmptyView()
}
}
}
}
}
}
struct PopupView: View {
@State var pin: PinAnnotation?
@State private var select: Int? = 0
var body: some View {
VStack (alignment: .leading) {
HStack {
if let val = pin {
Text(val.text)
.font(.system(size: 12, weight: .light, design: .default))
NavigationLink(destination: DetailsView(), label: {
Button(action: {select = 1}){
Image(systemName: "play.circle")
}
.scaledToFit()
.frame(width: 50, height: 50)
.background(Color.blue)
.foregroundColor(.white)
.clipShape(Circle())
})
} else {
Text("no data")
}
}
// .fixedSize()
}
.scaledToFit()
.foregroundStyle(.purple)
.frame(maxWidth: .infinity)
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
.offset(x: 0, y: -45)
}
}
struct DetailsView: View {
@Environment(\.presentationMode) var presentation
var body: some View {
Group {
Button("Back") {
self.presentation.wrappedValue.dismiss()
}
}
}
}
}
Hey, I have a problem. I was using MKMapView in my app, and in the view where I had a background at the top of the screen, in the example it was Color.red, it extended all the way to the top of the screen. Now, I wanted to switch to the newer Map and I'm seeing an issue because I'm getting a navigation bar that cuts off my color as I indicated in the picture. Does anyone know why this is happening and if there's another way to achieve this?
Steps to reproduce:
Change MapView() to Map() to see difference
import SwiftUI
import MapKit
@main
struct TestAppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
ScrollView(.vertical) {
Color.red
.padding(.top, -200)
.frame(height: 200)
MapView().frame(minHeight: 300) // change this line to Map
}
.navigationTitle("Title")
.navigationBarTitleDisplayMode(.large)
}
}
}
private typealias ViewControllerRepresentable = UIViewControllerRepresentable
struct MapView: ViewControllerRepresentable {
typealias ViewController = UIViewController
class Controller: ViewController {
var mapView: MKMapView {
guard let tempView = view as? MKMapView else {
fatalError("View could not be cast as MapView.")
}
return tempView
}
override func loadView() {
let mapView = MKMapView()
view = mapView
}
}
func makeUIViewController(context: Context) -> Controller {
Controller()
}
func updateUIViewController(_ controller: Controller, context: Context) {
update(controller: controller)
}
func update(controller: Controller) {
}
}
#Preview {
ContentView()
}
I got:
I want:
Hey, I have a problem. I was using MKMapView in my app, and in the view where I had a background at the top of the screen, in the example it was Color.red, it extended all the way to the top of the screen. Now, I wanted to switch to the newer Map and I'm seeing an issue because I'm getting a navigation bar that cuts off my color as I indicated in the picture. Does anyone know why this is happening and if there's another way to achieve this?
Steps to reproduce:
Change MapView() to Map() to see difference
import SwiftUI
import MapKit
@main
struct TestAppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
ScrollView(.vertical) {
Color.red
.padding(.top, -200)
.frame(height: 200)
MapView().frame(minHeight: 300) // change this line to Map
}
.navigationTitle("Title")
.navigationBarTitleDisplayMode(.large)
}
}
}
private typealias ViewControllerRepresentable = UIViewControllerRepresentable
struct MapView: ViewControllerRepresentable {
typealias ViewController = UIViewController
class Controller: ViewController {
var mapView: MKMapView {
guard let tempView = view as? MKMapView else {
fatalError("View could not be cast as MapView.")
}
return tempView
}
override func loadView() {
let mapView = MKMapView()
view = mapView
}
}
func makeUIViewController(context: Context) -> Controller {
Controller()
}
func updateUIViewController(_ controller: Controller, context: Context) {
update(controller: controller)
}
func update(controller: Controller) {
}
}
#Preview {
ContentView()
}
I got:
I want:
Hello,
There are some countries, with political conflicts on borders, does MapKit JS support displaying the map depending on the point of view of the region ?
if yes, how technically is done (like adding an attribute region on request params or something else) ?
Thanks
I have indoor map and I want to draw path between two route location ex. from A to B I want to draw ARKit based Arrow path in ios Application. Currently I am using ARAnchor to achieve this but challenges is if A to B is 10 meter and I am adding Nodes on each one meter so instead of 10 different nodes i am getting single Arrow nodes showing all 10 in it. I am using below code.
// Below Code from where I am calling addArpath function
if let lat1 = mCurrentPosition?.latitude, let long1 = mCurrentPosition?.longitude {
let latEnd = steplocation.latitude
let longEnd = steplocation.longitude
// if let lastLat = arrpath.last?.latitude,let lastLong = arrpath.last?.longitude,let lastAltitude = arrpath.last?.altitude{
let userLocation = CLLocation(latitude: lat1, longitude: long1)
let endLocation = CLLocation(coordinate: CLLocationCoordinate2DMake(CLLocationDegrees(latEnd), CLLocationDegrees(longEnd)), altitude: CLLocationDistance(steplocation.altitude), horizontalAccuracy: CLLocationAccuracy(5), verticalAccuracy: CLLocationAccuracy(0), course: CLLocationDirection(-1), speed: CLLocationSpeed(5), timestamp: Date())
let heading = getHeadingForDirectionFromCoordinate(from: userLocation, to: endLocation)
let lon1 = degreesToRadians(long1) //DegreesToRadians(long1)
let lon2 = degreesToRadians(longEnd); //DegreesToRadians(longEnd);
let lat2 = degreesToRadians(latEnd);
let dLon = lon2 - lon1
let y = sin(dLon) * cos(lat2);
yVal = yVal + y
// let distanceToendpoint = calculateDistance(lat: endLocation.coordinate.latitude, long: endLocation.coordinate.longitude)
let distvalue = Int(distance) + Int(pathlength)
distance += CGFloat(distvalue)
for i in stride(from: 0, to: distance, by:1) {
print("current loop iteration is:" ,i)
let headingValue = heading - self.heading
zValue = zValue + headingValue
distanceVal = CGFloat(i) + distanceVal
zGlobal = zValue
// Calling addARPathtoLocation
addARPathtoLocation(stepLocation:endLocation,zvalue: zValue, yvalue: yVal, distance:Float(i), direction: manuoverType)
}
// }
}
// MARK: - ARSessionDelegate
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard !(anchor is ARPlaneAnchor) else { return }
let sphereNode = generateArrowNodes(anchor: anchor)
DispatchQueue.main.async {
node.addChildNode(sphereNode)
}
}
//create ARAnchor to add to nodes
func generateArrowNodes(anchor: ARAnchor) -> SCNNode {
let imageMaterial = SCNMaterial()
imageMaterial.isDoubleSided = true
imageMaterial.diffuse.contents = UIImage(named: "blueArrow")
let plane = SCNPlane(width:0.5, height:0.5)
plane.materials = [imageMaterial]
plane.firstMaterial?.isDoubleSided = true
let blueNode = SCNNode(geometry: plane)
blueNode.name = "blueNode"
blueNode.position = SCNVector3(x:Float(zGlobal), y:0, z:Float(distanceVal))
blueNode.eulerAngles.x = -.pi / 2
blueNode.eulerAngles.y -= Float(CGFloat(CGFloat.pi/4*6))
return blueNode
}
func addARPathtoLocation(stepLocation: CLLocation, zvalue: CGFloat, yvalue: CGFloat, distance:Float, direction:VMEManeuverType) {
// give you the depth of anything ARKit has detected
guard let query = sceneView.raycastQuery(from: sceneView.center , allowing: .estimatedPlane, alignment: .any) else {
return
}
let results = sceneView.session.raycast(query)
guard let hitResult = results.first else {
print("No surface found")
return
}
// Add ARAnchor to Scene
let anchor = ARAnchor(transform: hitResult.worldTransform)
sceneView.session.add(anchor: anchor)
}
func radiansToDegrees(_ radians: Double) -> Double {
return (radians) * (180.0 / Double.pi)
}
func degreesToRadians(_ degrees: Double) -> Double {
return (degrees) * (Double.pi / 180.0)
}
func getHeadingForDirectionFromCoordinate(from: CLLocation, to: CLLocation) -> Double {
let fLat = degreesToRadians(from.coordinate.latitude)
let fLng = degreesToRadians(from.coordinate.longitude)
let tLat = degreesToRadians(to.coordinate.latitude)
let tLng = degreesToRadians(to.coordinate.longitude)
let deltaL = tLng - fLng
let x = sin(deltaL) * cos(tLng) //cos(tLat) * sin(deltaL)
let y = cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(deltaL)
let bearing = atan2(x,y)
let bearingInDegrees = bearing.toDegrees
print("Bearing Degrees :",bearingInDegrees) // sanity check
// let degree = radiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)))
if bearingInDegrees >= 0 {
return bearingInDegrees
} else {
return bearingInDegrees + 360
}
}
Hi all,
It wasn't extensively covered in the "Unlock the power of places with MapKit" at WWDC, but is it possible to add your own views to the mapItemDetailAccessory? The default view is great, but I would like to add a button for opening a new window showing another view. The documentation is rather limited at the moment so I thought I would ask here.
Thanks in advance.
I'm creating an app where I'm recreating how Apple Maps shows the user location button - i.e, in a stack with a background. I'd like the MapUserLocationButton to follow the styling that it does in Apple Maps (i.e., when locked to the user location, it switches to a filled icon, instead of colouring the background. Is there a way to do this?
I'm on MacOS 15 Beta and Xcode 16 Beta. Running iOS 18 Beta on a 15 Pro Max.
I'm leveraging the .mapItemDetailSheet(item: input) option to pull up a sheet that displays the Place Card for a selection made from a List of places.
This is working great on my iPhone 15 Pro Max and my iPad Pro 13.
I also have the Mac Catalyst option added under:
Project \ General \ Supported Destinations
If I launch the app from Xcode via the play button, the app functions fine on my MacBook Pro and I get logs in Xcode, etc.
However, if stop the session in Xcode and attempt to run the same app on its own on my MacBook Pro, the mapItemDetailSheet does not populate with any information.
Anyone have ideas on where the disconnect could be? Why would the sheet populate with data when ran from Xcode but not when ran on its own?
Again, it runs fine on the iPhone and iPad. Any ideas would be helpful and appreciated.
I have been developing an app that includes some pinned locations. These are displayed on a map, and currently have the standard pins and SF Symbol pins. A few of the locations have a special symbol on Apple Maps, but the same symbol is not avalable in SF Symbols. I was wondering if it is possible to use the pins, other than the standard red, from Apple Maps.
I'm on MacOS 15 Beta and Xcode 16 Beta.
Running iOS 18 Beta on a 15 Pro Max.
I'm leveraging the .mapItemDetailSheet(item: input) option to pull up a sheet that displays the Place Card for a selection made from a List of places.
What I'm seeing is that the first tap fails to pull up the sheet and it auto closes pretty much immediately. But then loads correctly on the second tap.
Other times it will not auto close, but simply fail to load the item details in the sheet. Again, though, if I close the sheet and tap a second time it loads without issue.
I'm posting to get some feedback as to whether this is most likely caused by bad code (I'm very new to this) or if it is known behavior and due to the Beta software. Any insight from the community would be helpful.
Thanks in advance.
Hello, I'm very interested in utilizing Place ID with MapKit.
Reference: https://developer.apple.com/videos/play/wwdc2024/10097/
I do have some questions I've been unable to find in documentation or within the demo. Apologies in advance if they have been added since.
Are place photos included with the call? It appeared so in the demo just want to make sure as I was unable to confirm in the documentation.)
Are star ratings included with the Place ID? Reason: Looking for ways to display top/popular POI around a location.
How do rate limits work?
Can places be cached? (We're looking to keep saved/bookmarked POI cached to avoid pinging MapKit each time the app is used)
How often is place data refreshed? For example if a new restaurant opens in town when will it be available to display.
Can search provide place results by name (in and out burger) and by type (burgers in LA)? Would we have to pick one way or the other for search to work in this case?
Thanks in advance.
I hope to use SwiftUI and MapKit to achieve the effect of a globe view when zooming out on the map. The code works in Xcode’s simulator and Simulator, but when running on my iPhone, it only zooms out to a flat world map. I haven’t found anyone else encountering the same issue, so I’d like to ask where the problem might be. Below is the simple code:
import SwiftUI
import MapKit
struct GlobalTest: View {
var body: some View {
Map(position: .constant(.automatic), interactionModes: [.all, .pan, .pitch, .rotate, .zoom]) {
}
.mapStyle(.hybrid(elevation: .realistic,
pointsOfInterest: .including([.park]),
showsTraffic: false))
}
}
#Preview {
GlobalTest()
}
I have also tried setting the camera properties, but it still doesn’t work. My phone is an iPhone 15 Pro Max, running iOS 17.5.1, and I am in mainland China. The Xcode version is the latest. If anyone understands the reason, please let me know. This is very important to me, and I would be very grateful!
Is MultiPolygon overlay support going to be integrated with SwiftUI?
I have made a post on here previously without a reply :(
Any suggestions on how to display multi-polygons within MapKit for SwiftUI(https://developer.apple.com/documentation/mapkit/mappolygon)?
At the moment it is not supported and only supported by MapKit for UIKit(https://developer.apple.com/documentation/mapkit/mkmultipolygon).
I'm looking at the new beta features for MapKit in SwiftUI, does anyone know if it's possible to create a map annotation callout or popover from a custom view?
Edit: The issue was resolved. It's back up.
I was streaming the new MapKit Places video, and it suddenly stopped. It's now missing from the Developer app and website. Is this intentional?
Description:
I am working on an iOS 17 app using Xcode 15 and SwiftUI. The app involves displaying points of interest (POIs) on a MapView based on user proximity and other factors such as hours of operation. The data for the POIs is stored in a JSON file, which I am trying to import and parse in the project. However, I have encountered several issues:
Deprecation Errors:
When attempting to use MapAnnotation, I receive deprecation warnings and errors. It seems that MapAnnotation has been deprecated in iOS 17, and I need to use the new Annotation API along with MapContentBuilder.
RandomAccessCollection Conformance:
Errors related to RandomAccessCollection conformance when using Map with SwiftUI.
JSON Import and Parsing:
I used Bundle.main.url(forResource: "locations", withExtension: "json") to load the JSON file but faced issues with correctly parsing and mapping the JSON data to my model objects.
What I Need:
Guidance on how to correctly use the new Annotation API and MapContentBuilder for displaying POIs on a MapView in iOS 17.
Best practices for importing and parsing JSON files in SwiftUI, especially for dynamically updating the MapView based on user proximity and other criteria like hours of operation.
Any relevant code snippets or examples would be greatly appreciated.
Example of What We Tried
Model:
swift
Copy code
struct POI: Codable, Identifiable {
let id: Int
let name: String
let latitude: Double
let longitude: Double
let hours: [String: String]
}
Loading JSON:
swift
Copy code
func loadPOIs() -> [POI] {
guard let url = Bundle.main.url(forResource: "locations", withExtension: "json"),
let data = try? Data(contentsOf: url) else {
return []
}
let decoder = JSONDecoder()
return (try? decoder.decode([POI].self, from: data)) ?? []
}
Map View:
swift
Copy code
import SwiftUI
import MapKit
struct ContentView: View {
@State private var pois: [POI] = loadPOIs()
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 40.7128, longitude: -74.0060),
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
var body: some View {
Map(coordinateRegion: $region, annotationItems: pois) { poi in
MapAnnotation(coordinate: CLLocationCoordinate2D(latitude: poi.latitude, longitude: poi.longitude)) {
VStack {
Text(poi.name)
Circle().fill(Color.red).frame(width: 10, height: 10)
}
}
}
}
}
Issues Encountered:
MapAnnotation is deprecated.
Errors related to RandomAccessCollection conformance.
Any advice or solutions for these issues would be greatly appreciated. Thank you!