
Implementing Look Around with MapKit in SwiftUI
Learn how to provide an interactive 3d street-level experience within your SwiftUI app.
When it comes to providing geographical information using the MapKit framework, users can access the Look Around feature, which provides an interactive 3D street-level experience. In this article, we will see how we can integrate the Look Around API for our SwiftUI apps.
We will start by defining a simple class that will control the scene that needs to be displayed using Look Around.
import MapKit
@Observable
class LookAroundManager {
var lookAroundScene: MKLookAroundScene?
var coordinate: CLLocationCoordinate2D?
}
This LookAroundManager
class has two properties:
lookAroundScene
: a variable that will store the information to retrieve and display a specific Look Around location’s imagery.coordinate
: a variable that will store aCLLocationCoordinate2D
object containing the latitude and longitude values.
What we need now is a method that is responsible for creating a request object with the coordinates and taking the scene from the request. We can define it within the LookAroundManager
class.
@Observable
class LookAroundManager {
var lookAroundScene: MKLookAroundScene?
var coordinate: CLLocationCoordinate2D?
func loadPreview() async {
Task {
if let coordinate = coordinate {
let request = MKLookAroundSceneRequest(coordinate: coordinate)
do {
lookAroundScene = try await request.scene
} catch (let error) {
print(error)
}
}
}
}
}
The loadPreview()
method defined in the example above is an async method because the request needs to be created in a concurrent environment. Within the Task
closure, we assign the scene
value from the request object to our lookAroundScene
property.
Now that we have everything set, we can use this class in a View
to display the LookAroundPreview
on our apps.
import SwiftUI
import MapKit
struct ContentView: View {
@State var lookAroundManager = LookAroundManager()
var body: some View {
VStack {
Text("Apple Park")
.font(.title)
.fontDesign(.serif)
if let lookAroundScene = lookAroundManager.lookAroundScene {
LookAroundPreview(initialScene: lookAroundScene)
.clipShape(RoundedRectangle(cornerRadius: 25))
.frame(height: 300)
.padding()
} else {
ContentUnavailableView("Look Around Preview not available", systemImage: "mappin.and.ellipse")
}
}
.task {
lookAroundManager.coordinates = CLLocationCoordinate2D(
latitude: 37.334606,
longitude: -122.00585
)
await lookAroundManager.loadPreview()
}
}
}
In addition to the LookAroundPreview
object, we can also use the lookAroundViewer(isPresented:initialScene:)
modifier that will present the look around visualization as a modal:
import SwiftUI
import MapKit
struct ContentView: View {
@State var lookAroundManager = LookAroundManager()
@State var isLookingAround = false
var body: some View {
VStack {
Text("Apple Park")
.font(.title)
.fontDesign(.serif)
if let lookAroundScene = lookAroundManager.lookAroundScene {
RoundedRectangle(cornerRadius: 25)
.padding()
.frame(height: 300)
Button("Show Look Around"){
isLookingAround.toggle()
}
}
}
.lookAroundViewer(
isPresented: $isLookingAround,
initialScene: lookAroundManager.lookAroundScene
)
.task {
lookAroundManager.coordinates = CLLocationCoordinate2D(
latitude: 40.836639,
longitude: 14.306602
)
await lookAroundManager.loadPreview()
}
}
}
Customization options
The Look Around feature in MapKit offers several customization options through its preview and viewer modifiers. You can control the navigation behavior by setting the allowsNavigation
parameter - when set to false, it keeps the view fixed at the specified coordinates, while if set to true, it enables free navigation.
The visibility of road labels can be toggled using the showsRoadLabels
parameter, letting you choose whether street names appear in the view.
Additionally, you can filter which points of interest appear during navigation by passing a PointsOfInterestCategories
object to the pointsOfInterest
property, giving you precise control over the types of locations highlighted in the Look Around experience.
import SwiftUI
import MapKit
struct ContentView: View {
@State var lookAroundManager = LookAroundManager()
var body: some View {
VStack {
Text("Apple Park")
.font(.title)
.fontDesign(.serif)
if let lookAroundScene = lookAroundManager.lookAroundScene {
LookAroundPreview(
initialScene: lookAroundScene,
allowsNavigation: false,
showsRoadLabels: false,
pointsOfInterest: .all,
badgePosition: .topTrailing
)
.clipShape(RoundedRectangle(cornerRadius: 25))
.frame(height: 300)
.padding()
} else {
ContentUnavailableView("Look Around Preview not available", systemImage: "mappin.and.ellipse")
}
}
.task {
lookAroundManager.coordinates = CLLocationCoordinate2D(
latitude: 37.334606,
longitude: -122.00585
)
await lookAroundManager.loadPreview()
}
}
}