āļŠāļąāļĄāļ āļēāļĐāļāđ MapKit SwiftUI āđāļāļāļĩ 2026: āļāļģāļāļāļīāļāļēāļĒāļāļĢāļ°āļāļāļ āļāļēāļĢāļāđāļāļāļāļąāļ āđāļĨāļ°āļāļēāļĢāļĢāļ°āļāļļāļāļģāđāļŦāļāđāļ
āđāļāļĩāđāļĒāļ§āļāļēāļ MapKit āļāđāļ§āļĒ SwiftUI āļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđ iOS: āļāļģāļāļāļīāļāļēāļĒāļāļĢāļ°āļāļāļāđāļāļāļāļģāļŦāļāļāđāļāļ āļāļēāļĢāļāđāļāļāļāļąāļ āļāļēāļĢāļĢāļ°āļāļļāļāļģāđāļŦāļāđāļ āļāļēāļĢāļāđāļāļŦāļēāļŠāļāļēāļāļāļĩāđ āđāļĨāļ°āļĢāļđāļāđāļāļāļāļēāļĢāļāļŠāļēāļāļĢāļ§āļĄāļāļąāļ Maps

āđāļāļāļāļĩāđāđāļāđāļāļāļļāļāļŠāļĄāļāļąāļāļīāļŦāļĨāļąāļāđāļāđāļāļāļāļĨāļīāđāļāļāļąāļ iOS āļŦāļĨāļēāļĒāļāļąāļ§ āđāļāđāđāļāđ āļāļēāļĢāļāļąāļāļŠāđāļ āļāļīāļāđāļāļŠ āļāļŠāļąāļāļŦāļēāļĢāļīāļĄāļāļĢāļąāļāļĒāđ āđāļĨāļ°āđāļāļĢāļ·āļāļāđāļēāļĒāļŠāļąāļāļāļĄāļāļēāļĄāļāļģāđāļŦāļāđāļ āļāļąāđāļāđāļāđ iOS 17 āđāļāđāļāļāđāļāļĄāļē MapKit āđāļāđāļāļąāļāđāļāļĢāļĩāļĒāļĄ API SwiftUI āđāļāļāđāļāļāļĩāļāļāļĩāđāļāļģāđāļŦāđāļāļēāļĢāļāļŠāļēāļāļĢāļ§āļĄāđāļāļāļāļĩāđāļāđāļēāļĒāļāļķāđāļāļāļĒāđāļēāļāļĄāļēāļ āļāļđāđāļŠāļĢāļĢāļŦāļēāļāļļāļāļĨāļēāļāļĢāļāļĢāļ°āđāļĄāļīāļāļāļąāļāļĐāļ°āđāļŦāļĨāđāļēāļāļĩāđāđāļāđāļāļāļĢāļ°āļāļģāđāļāļĢāļ°āļŦāļ§āđāļēāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđāļāļēāļāđāļāļāļāļīāļ
āđāļāđāļĨāļ°āļāļģāļāļēāļĄāļŠāļ°āļāđāļāļāļĢāļđāļāđāļāļāļāļāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđāļāļēāļāđāļāļāļāļīāļāļāļĢāļīāļ āļāļĢāđāļāļĄāļāļģāļāļāļāđāļāļĒāļĨāļ°āđāļāļĩāļĒāļāđāļĨāļ°āđāļāđāļāļāļĩāđāđāļāđāļāļēāļāđāļāđ āđāļāļ§āļāļīāļāļāļģāđāļāļīāļāđāļāļāļēāļāļĢāļ°āļāļąāļāļāļ·āđāļāļāļēāļāļāļķāļāļĢāļ°āļāļąāļāļŠāļđāļ
āļāļ·āđāļāļāļēāļāļāļāļāđāļāļāļāļĩāđāđāļ SwiftUI
āļāļģāļāļēāļĄāļāļĩāđ 1: āļāļ°āđāļŠāļāļāđāļāļāļāļĩāđāļāļ·āđāļāļāļēāļāļāđāļ§āļĒ SwiftUI āđāļāđāļāļĒāđāļēāļāđāļĢ?
āļāļąāđāļāđāļāđ iOS 17 āđāļāđāļāļāđāļāļĄāļē SwiftUI āđāļāđāļāļąāļāđāļāļĢāļĩāļĒāļĄāļāļāļĄāđāļāđāļāļāļāđ Map āđāļāļāđāļāļāļĩāļāļāļĩāđāđāļāļāļāļĩāđāđāļāļ§āļāļēāļ UIViewRepresentable āđāļāļāđāļāļīāļĄ Map view āļĒāļāļĄāļĢāļąāļāļāļģāđāļŦāļāđāļāļāļāļāļāļĨāđāļāļāđāļĨāļ°āđāļāļ·āđāļāļŦāļēāļāļĩāđāļāļ°āđāļŠāļāļ
import SwiftUI
import MapKit
struct BasicMapView: View {
// Camera position controlling center and zoom
@State private var cameraPosition: MapCameraPosition = .automatic
var body: some View {
// Basic map without additional content
Map(position: $cameraPosition)
}
}
// Map centered on a specific region
struct CenteredMapView: View {
// Defines a region centered on Paris
@State private var cameraPosition: MapCameraPosition = .region(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522),
// Span defines the zoom level (in degrees)
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
)
var body: some View {
Map(position: $cameraPosition) {
// Map content (markers, annotations, etc.)
}
.mapStyle(.standard) // Map style: standard, imagery, hybrid
}
}āļāļļāļāļŠāļĄāļāļąāļāļī position āđāļāđ MapCameraPosition āļāļķāđāļāđāļāđāļ enum āļāļĩāđāļāļāļļāļāļēāļāđāļŦāđāļĄāļĩāđāļŦāļĄāļāļāđāļēāļ āđ āđāļāđāđāļāđ .automatic (āļāļĢāļąāļāļāļąāļāđāļāļĄāļąāļāļī), .region (āļāļ·āđāļāļāļĩāđāļāļāļāļĩāđ), .camera (āļāļ§āļāļāļļāļĄāđāļāđāļĄāļāļĩāđ) āļŦāļĢāļ·āļ .userLocation (āļāļĒāļđāđāļāļĢāļāļāļĨāļēāļāļāļĩāđāļāļđāđāđāļāđ)
āļāļģāļāļēāļĄāļāļĩāđ 2: āļĄāļĩāļĢāļđāļāđāļāļāđāļāļāļāļĩāđāđāļāļāđāļēāļāđāļŦāđāđāļāđ?
MapKit āļĄāļĩāļĢāļđāļāđāļāļāđāļāļāļāļĩāđāļŦāļĨāļēāļĒāļĢāļđāļāđāļāļāļāļĩāđāđāļŦāļĄāļēāļ°āļŠāļĄāļāļąāļāļāļĢāļāļĩāļāļēāļĢāđāļāđāļāļēāļāļāđāļēāļ āđ Modifier .mapStyle() āļāļģāļŦāļāļāļĢāļđāļāļĨāļąāļāļĐāļāđāđāļāļīāļāļ āļēāļāļāļāļāđāļāļāļāļĩāđ
import SwiftUI
import MapKit
struct MapStylesDemo: View {
@State private var position: MapCameraPosition = .automatic
@State private var selectedStyle: MapStyleOption = .standard
var body: some View {
VStack {
Map(position: $position)
.mapStyle(selectedStyle.style)
.frame(height: 400)
// Style selector
Picker("Style", selection: $selectedStyle) {
ForEach(MapStyleOption.allCases) { option in
Text(option.name).tag(option)
}
}
.pickerStyle(.segmented)
.padding()
}
}
}
enum MapStyleOption: String, CaseIterable, Identifiable {
case standard
case imagery
case hybrid
case standardElevated
case imageryElevated
var id: String { rawValue }
var name: String {
switch self {
case .standard: return "Standard"
case .imagery: return "Satellite"
case .hybrid: return "Hybrid"
case .standardElevated: return "Terrain"
case .imageryElevated: return "Satellite 3D"
}
}
var style: MapStyle {
switch self {
case .standard:
// Classic road map
return .standard
case .imagery:
// Satellite view without labels
return .imagery
case .hybrid:
// Satellite with roads and names
return .hybrid
case .standardElevated:
// Standard with 3D terrain
return .standard(elevation: .realistic)
case .imageryElevated:
// Satellite with 3D terrain
return .imagery(elevation: .realistic)
}
}
}āļĢāļđāļāđāļāļ .standard āļĒāļāļĄāļĢāļąāļāļāļēāļĢāļēāļĄāļīāđāļāļāļĢāđ pointsOfInterest āđāļāļ·āđāļāļāļĢāļāļāļŦāļĄāļ§āļāļŦāļĄāļđāđāļāļĩāđāđāļŠāļāļ: .including([.restaurant, .cafe]) āļŦāļĢāļ·āļ .excluding([.nightlife])
āļāļģāļāļēāļĄāļāļĩāđ 3: āļāļ°āđāļāļīāđāļĄāđāļāļĢāļ·āđāļāļāļŦāļĄāļēāļĒāđāļĨāļ°āļāļģāļāļāļīāļāļēāļĒāļāļĢāļ°āļāļāļāļāļāđāļāļāļāļĩāđāđāļāđāļāļĒāđāļēāļāđāļĢ?
āđāļāļĢāļ·āđāļāļāļŦāļĄāļēāļĒāđāļāļāļāļļāļāļāļĩāđāļāđāļēāļŠāļāđāļāļāļāđāļāļāļāļĩāđ SwiftUI MapKit āļĄāļĩāļŦāļĨāļēāļĒāļāļĢāļ°āđāļ āļ āđāļāđāđāļāđ Marker (āļāļīāļāļĄāļēāļāļĢāļāļēāļ), Annotation (view āđāļāļāļāļģāļŦāļāļāđāļāļ) āđāļĨāļ° MapCircle/MapPolygon (āļĢāļđāļāļāļĢāļāđāļĢāļāļēāļāļāļīāļ)
import SwiftUI
import MapKit
// Place model conforming to Identifiable
struct Place: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
let category: PlaceCategory
}
enum PlaceCategory {
case restaurant, hotel, attraction
var icon: String {
switch self {
case .restaurant: return "fork.knife"
case .hotel: return "bed.double"
case .attraction: return "star"
}
}
var tint: Color {
switch self {
case .restaurant: return .orange
case .hotel: return .blue
case .attraction: return .purple
}
}
}
struct MarkersMapView: View {
@State private var position: MapCameraPosition = .region(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522),
span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
)
)
let places: [Place] = [
Place(name: "Eiffel Tower", coordinate: CLLocationCoordinate2D(latitude: 48.8584, longitude: 2.2945), category: .attraction),
Place(name: "Le Meurice", coordinate: CLLocationCoordinate2D(latitude: 48.8651, longitude: 2.3281), category: .hotel),
Place(name: "Le Jules Verne", coordinate: CLLocationCoordinate2D(latitude: 48.8583, longitude: 2.2944), category: .restaurant)
]
var body: some View {
Map(position: $position) {
// Markers with system icon
ForEach(places) { place in
Marker(place.name, systemImage: place.category.icon, coordinate: place.coordinate)
.tint(place.category.tint)
}
}
}
}
// Custom annotations with SwiftUI view
struct CustomAnnotationsView: View {
@State private var position: MapCameraPosition = .automatic
@State private var selectedPlace: Place?
let places: [Place] = [] // Data
var body: some View {
Map(position: $position, selection: $selectedPlace) {
ForEach(places) { place in
// Annotation with custom view
Annotation(place.name, coordinate: place.coordinate) {
PlaceAnnotationView(place: place, isSelected: selectedPlace?.id == place.id)
}
}
}
}
}
// Custom view for annotation
struct PlaceAnnotationView: View {
let place: Place
let isSelected: Bool
var body: some View {
VStack(spacing: 4) {
// Icon with colored background
Image(systemName: place.category.icon)
.font(.system(size: isSelected ? 20 : 16))
.foregroundStyle(.white)
.padding(8)
.background(place.category.tint)
.clipShape(Circle())
.shadow(radius: 4)
// Name displayed when selected
if isSelected {
Text(place.name)
.font(.caption)
.fontWeight(.medium)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
.animation(.spring(duration: 0.3), value: isSelected)
}
}āļāļ§āļēāļĄāđāļāļāļāđāļēāļāļŦāļĨāļąāļ: Marker āđāļāđāļāļēāļĢāđāļŠāļāļāļāļĨāđāļāļāđāļāļāļĩāļāļāļāļ Apple Maps (āļāļīāļāļĄāļēāļāļĢāļāļēāļ) āđāļāļāļāļ°āļāļĩāđ Annotation āļāļāļļāļāļēāļāđāļŦāđāļāļĢāļąāļāđāļāđāļāđāļāđāļāļĒāđāļēāļāļŠāļĄāļāļđāļĢāļāđāļāđāļ§āļĒ view āđāļ āđ āļāļāļ SwiftUI
āļāļēāļĢāļĢāļ°āļāļļāļāļģāđāļŦāļāđāļāđāļĨāļ°āļāļēāļĢāļāļāļļāļāļēāļ
āļāļģāļāļēāļĄāļāļĩāđ 4: āļāļ°āļāļąāļāļāļēāļĢāļāļēāļĢāļāļāļļāļāļēāļāļāļģāđāļŦāļāđāļāđāļĨāļ°āđāļŠāļāļāļāļģāđāļŦāļāđāļāļāļāļāļāļđāđāđāļāđāđāļāđāļāļĒāđāļēāļāđāļĢ?
āļāļēāļĢāļĢāļ°āļāļļāļāļģāđāļŦāļāđāļāļāđāļāļāļāļēāļĢāļāļēāļĢāļāļāļļāļāļēāļāļāļĒāđāļēāļāļāļąāļāđāļāļāđāļĨāļ°āļāļēāļĢāļāļąāļāļāļēāļĢāļŠāļāļēāļāļ°āļāļēāļĢāļāļāļļāļāļēāļāļāđāļēāļ āđ āļāļĒāđāļēāļāđāļŦāļĄāļēāļ°āļŠāļĄ CLLocationManager āļāļđāđāļĨāļāļēāļĢāļāļāļāļāļļāļāļēāļ
import SwiftUI
import MapKit
import CoreLocation
@Observable
class LocationManager: NSObject, CLLocationManagerDelegate {
private let manager = CLLocationManager()
// Location state
var location: CLLocation?
var authorizationStatus: CLAuthorizationStatus = .notDetermined
var isAuthorized: Bool {
authorizationStatus == .authorizedWhenInUse || authorizationStatus == .authorizedAlways
}
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
// Get current status
authorizationStatus = manager.authorizationStatus
}
// Request location permission
func requestAuthorization() {
manager.requestWhenInUseAuthorization()
}
// Start location tracking
func startUpdatingLocation() {
guard isAuthorized else { return }
manager.startUpdatingLocation()
}
// Stop tracking to save battery
func stopUpdatingLocation() {
manager.stopUpdatingLocation()
}
// MARK: - CLLocationManagerDelegate
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
authorizationStatus = manager.authorizationStatus
if isAuthorized {
startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Take the most recent position
location = locations.last
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Location error: \(error.localizedDescription)")
}
}
// View with map and user location
struct UserLocationMapView: View {
@State private var locationManager = LocationManager()
@State private var cameraPosition: MapCameraPosition = .userLocation(fallback: .automatic)
var body: some View {
Map(position: $cameraPosition) {
// Display the blue user location dot
UserAnnotation()
}
.mapControls {
// Button to recenter on position
MapUserLocationButton()
// Compass
MapCompass()
// Scale
MapScaleView()
}
.onAppear {
locationManager.requestAuthorization()
}
.overlay(alignment: .top) {
if !locationManager.isAuthorized {
PermissionBanner()
}
}
}
}
// Banner requesting authorization
struct PermissionBanner: View {
var body: some View {
HStack {
Image(systemName: "location.slash")
Text("Enable location in Settings")
Spacer()
Button("Open") {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
}
.buttonStyle(.bordered)
}
.padding()
.background(.ultraThinMaterial)
}
}āļāļĩāļĒāđ NSLocationWhenInUseUsageDescription āđāļĨāļ°/āļŦāļĢāļ·āļ NSLocationAlwaysUsageDescription āļāđāļāļāļāļđāļāļāļģāļŦāļāļāđāļ Info.plist āļāļĢāđāļāļĄāļāļģāļāļāļīāļāļēāļĒāļāļĩāđāļāļąāļāđāļāļāđāļāļĩāđāļĒāļ§āļāļąāļāļāļēāļĢāđāļāđāļāļģāđāļŦāļāđāļ
āļāļģāļāļēāļĄāļāļĩāđ 5: āļāļ°āļāļīāļāļāļēāļĄāļāļģāđāļŦāļāđāļāđāļāļāđāļĢāļĩāļĒāļĨāđāļāļĄāđāđāļĨāļ°āļ§āļēāļāđāļŠāđāļāļāļēāļāđāļāđāļāļĒāđāļēāļāđāļĢ?
āļāļēāļĢāļāļīāļāļāļēāļĄāđāļāļāđāļĢāļĩāļĒāļĨāđāļāļĄāđāđāļāđāļāļŠāļīāđāļāļāļģāđāļāđāļāļŠāļģāļŦāļĢāļąāļāđāļāļāļāļīāļāđāļāļŠāļŦāļĢāļ·āļāļāļēāļĢāļāļģāļāļēāļ āļāļģāļāļēāļĄāļāļĩāđāļāļāļŠāļāļāļāļ§āļēāļĄāļŠāļēāļĄāļēāļĢāļāđāļāļāļēāļĢāļāļąāļāļāļēāļĢāļāļĢāļ°āđāļŠāļāđāļāļĄāļđāļĨāļāļģāđāļŦāļāđāļāļāļĒāđāļēāļāļāđāļāđāļāļ·āđāļāļ
import SwiftUI
import MapKit
import CoreLocation
@Observable
class RouteTracker: NSObject, CLLocationManagerDelegate {
private let manager = CLLocationManager()
// Position history for the trace
var routeCoordinates: [CLLocationCoordinate2D] = []
var currentLocation: CLLocation?
var isTracking = false
// Route statistics
var totalDistance: CLLocationDistance = 0
private var lastLocation: CLLocation?
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
// Update even in background
manager.allowsBackgroundLocationUpdates = true
manager.pausesLocationUpdatesAutomatically = false
}
func startTracking() {
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
isTracking = true
routeCoordinates = []
totalDistance = 0
lastLocation = nil
}
func stopTracking() {
manager.stopUpdatingLocation()
isTracking = false
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let newLocation = locations.last else { return }
// Filter inaccurate positions
guard newLocation.horizontalAccuracy < 20 else { return }
currentLocation = newLocation
routeCoordinates.append(newLocation.coordinate)
// Calculate distance traveled
if let last = lastLocation {
totalDistance += newLocation.distance(from: last)
}
lastLocation = newLocation
}
}
struct RouteTrackingView: View {
@State private var tracker = RouteTracker()
@State private var cameraPosition: MapCameraPosition = .userLocation(fallback: .automatic)
var body: some View {
ZStack {
Map(position: $cameraPosition) {
// Current position
UserAnnotation()
// Route trace as polyline
if tracker.routeCoordinates.count > 1 {
MapPolyline(coordinates: tracker.routeCoordinates)
.stroke(.blue, lineWidth: 4)
}
}
.mapStyle(.standard)
// Control interface
VStack {
Spacer()
// Statistics
HStack {
VStack(alignment: .leading) {
Text("Distance")
.font(.caption)
.foregroundStyle(.secondary)
Text(formatDistance(tracker.totalDistance))
.font(.title2)
.fontWeight(.bold)
}
Spacer()
}
.padding()
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding()
// Start/stop button
Button {
if tracker.isTracking {
tracker.stopTracking()
} else {
tracker.startTracking()
}
} label: {
Label(
tracker.isTracking ? "Stop" : "Start",
systemImage: tracker.isTracking ? "stop.fill" : "play.fill"
)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.tint(tracker.isTracking ? .red : .green)
.padding(.horizontal)
.padding(.bottom)
}
}
}
private func formatDistance(_ meters: CLLocationDistance) -> String {
if meters < 1000 {
return String(format: "%.0f m", meters)
} else {
return String(format: "%.2f km", meters / 1000)
}
}
}āļāļĢāđāļāļĄāļāļĩāđāļāļ°āļāļīāļāļīāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđ iOS āđāļĨāđāļ§āļŦāļĢāļ·āļāļĒāļąāļāļāļĢāļąāļ?
āļāļķāļāļāļāļāđāļ§āļĒāļāļąāļ§āļāļģāļĨāļāļāđāļāļāđāļāđāļāļāļ, flashcards āđāļĨāļ°āđāļāļāļāļāļŠāļāļāđāļāļāļāļīāļāļāļĢāļąāļ
āļāļēāļĢāļāđāļāļāļāļąāļāđāļĨāļ°āļĢāļđāļāļāļĢāļāđāļĢāļāļēāļāļāļīāļ
āļāļģāļāļēāļĄāļāļĩāđ 6: āļāļ°āļ§āļēāļāļāļēāļĢāļāđāļāļāļāļąāļāđāļāļāļāļģāļŦāļāļāđāļāļāļāļāđāļāļāļāļĩāđāđāļāđāļāļĒāđāļēāļāđāļĢ?
āļāļēāļĢāļāđāļāļāļāļąāļāļāđāļ§āļĒāđāļŦāđāđāļŠāļāļāđāļāļ āđāļŠāđāļāļāļēāļ āļŦāļĢāļ·āļāļāļ·āđāļāļāļĩāđāļāļāđāļāļāļāļĩāđāđāļāđ SwiftUI MapKit āļĄāļĩ MapCircle, MapPolygon āđāļĨāļ° MapPolyline
import SwiftUI
import MapKit
struct DeliveryZoneMapView: View {
@State private var position: MapCameraPosition = .region(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522),
span: MKCoordinateSpan(latitudeDelta: 0.15, longitudeDelta: 0.15)
)
)
// Delivery zones with different times
let deliveryZones: [DeliveryZone] = [
DeliveryZone(
name: "Express Zone",
center: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522),
radius: 2000,
deliveryTime: "15 min",
color: .green
),
DeliveryZone(
name: "Standard Zone",
center: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522),
radius: 5000,
deliveryTime: "30 min",
color: .orange
)
]
var body: some View {
Map(position: $position) {
// Circles for delivery zones
ForEach(deliveryZones) { zone in
MapCircle(center: zone.center, radius: zone.radius)
.foregroundStyle(zone.color.opacity(0.2))
.stroke(zone.color, lineWidth: 2)
}
// Restaurant marker
Marker("Restaurant", systemImage: "storefront", coordinate: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522))
.tint(.red)
}
.overlay(alignment: .bottomLeading) {
// Legend
VStack(alignment: .leading, spacing: 8) {
ForEach(deliveryZones) { zone in
HStack {
Circle()
.fill(zone.color)
.frame(width: 12, height: 12)
Text("\(zone.name) - \(zone.deliveryTime)")
.font(.caption)
}
}
}
.padding()
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 8))
.padding()
}
}
}
struct DeliveryZone: Identifiable {
let id = UUID()
let name: String
let center: CLLocationCoordinate2D
let radius: CLLocationDistance
let deliveryTime: String
let color: Color
}
// Custom polygon (complex geographic zone)
struct PolygonOverlayView: View {
@State private var position: MapCameraPosition = .automatic
// Neighborhood coordinates
let neighborhoodCoordinates: [CLLocationCoordinate2D] = [
CLLocationCoordinate2D(latitude: 48.853, longitude: 2.347),
CLLocationCoordinate2D(latitude: 48.858, longitude: 2.352),
CLLocationCoordinate2D(latitude: 48.862, longitude: 2.348),
CLLocationCoordinate2D(latitude: 48.860, longitude: 2.340),
CLLocationCoordinate2D(latitude: 48.855, longitude: 2.342)
]
var body: some View {
Map(position: $position) {
// Polygon automatically closed
MapPolygon(coordinates: neighborhoodCoordinates)
.foregroundStyle(.blue.opacity(0.3))
.stroke(.blue, lineWidth: 3)
}
}
}āļāļģāļāļēāļĄāļāļĩāđ 7: āļāļ°āđāļŠāļāļāđāļŠāđāļāļāļēāļāļĢāļ°āļŦāļ§āđāļēāļāļŠāļāļāļāļļāļāđāļāđāļāļĒāđāļēāļāđāļĢ?
āļāļēāļĢāļāļģāļāļ§āļāđāļŠāđāļāļāļēāļāđāļāđ MKDirections āđāļāļ·āđāļāļĢāļąāļāđāļŠāđāļāļāļēāļāļāļēāļāđāļāļīāļĢāđāļāđāļ§āļāļĢāđāļāļāļ Apple āļāļēāļāļāļąāđāļāļāļ°āđāļŠāļāļāļāļĨāļāđāļ§āļĒ MapPolyline
import SwiftUI
import MapKit
@Observable
class RouteCalculator {
var route: MKRoute?
var isCalculating = false
var error: String?
// Calculate route between two points
func calculateRoute(from source: CLLocationCoordinate2D, to destination: CLLocationCoordinate2D) async {
isCalculating = true
error = nil
// Create source and destination placemarks
let sourcePlacemark = MKPlacemark(coordinate: source)
let destinationPlacemark = MKPlacemark(coordinate: destination)
// Configure request
let request = MKDirections.Request()
request.source = MKMapItem(placemark: sourcePlacemark)
request.destination = MKMapItem(placemark: destinationPlacemark)
request.transportType = .automobile // .walking, .transit available
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
do {
let response = try await directions.calculate()
// Take the first route
route = response.routes.first
} catch {
self.error = error.localizedDescription
}
isCalculating = false
}
}
struct DirectionsMapView: View {
@State private var calculator = RouteCalculator()
@State private var position: MapCameraPosition = .automatic
let startPoint = CLLocationCoordinate2D(latitude: 48.8738, longitude: 2.2950) // Arc de Triomphe
let endPoint = CLLocationCoordinate2D(latitude: 48.8530, longitude: 2.3499) // Notre-Dame
var body: some View {
ZStack {
Map(position: $position) {
// Start and end markers
Marker("Start", systemImage: "car.fill", coordinate: startPoint)
.tint(.green)
Marker("End", systemImage: "flag.fill", coordinate: endPoint)
.tint(.red)
// Route trace
if let route = calculator.route {
MapPolyline(route.polyline)
.stroke(.blue, lineWidth: 5)
}
}
// Route information
if let route = calculator.route {
VStack {
Spacer()
RouteInfoCard(route: route)
}
}
if calculator.isCalculating {
ProgressView("Calculating route...")
.padding()
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}
.task {
await calculator.calculateRoute(from: startPoint, to: endPoint)
}
}
}
struct RouteInfoCard: View {
let route: MKRoute
var body: some View {
HStack(spacing: 20) {
VStack(alignment: .leading) {
Text("Distance")
.font(.caption)
.foregroundStyle(.secondary)
Text(formatDistance(route.distance))
.font(.headline)
}
Divider()
.frame(height: 30)
VStack(alignment: .leading) {
Text("Estimated Time")
.font(.caption)
.foregroundStyle(.secondary)
Text(formatDuration(route.expectedTravelTime))
.font(.headline)
}
Spacer()
}
.padding()
.background(.ultraThinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12))
.padding()
}
private func formatDistance(_ meters: CLLocationDistance) -> String {
let km = meters / 1000
return String(format: "%.1f km", km)
}
private func formatDuration(_ seconds: TimeInterval) -> String {
let minutes = Int(seconds) / 60
if minutes < 60 {
return "\(minutes) min"
} else {
let hours = minutes / 60
let remainingMinutes = minutes % 60
return "\(hours)h \(remainingMinutes)min"
}
}
}āļāļēāļĢāļāđāļāļŦāļēāļŠāļāļēāļāļāļĩāđāđāļĨāļ°āļāļēāļĢāđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđ
āļāļģāļāļēāļĄāļāļĩāđ 8: āļāļ°āđāļāđāļāļēāļāļāļēāļĢāļāđāļāļŦāļēāļŠāļāļēāļāļāļĩāđāļāđāļ§āļĒ MKLocalSearch āđāļāđāļāļĒāđāļēāļāđāļĢ?
MKLocalSearch āļāđāļ§āļĒāđāļŦāđāļŠāļēāļĄāļēāļĢāļāļāđāļāļŦāļēāļāļļāļāļāļĩāđāļāđāļēāļŠāļāđāļ āļāļĩāđāļāļĒāļđāđ āļŦāļĢāļ·āļāļāļļāļĢāļāļīāļāđāļāđ āļāļļāļāļŠāļĄāļāļąāļāļīāļāļĩāđāđāļāđāļāļŠāļīāđāļāļāļģāđāļāđāļāļŠāļģāļŦāļĢāļąāļāđāļāļāļāļĨāļīāđāļāļāļąāļāļāļĩāđāļĄāļĩāđāļāļāļāđāļāļŦāļēāļāļēāļĄāļāļģāđāļŦāļāđāļ
import SwiftUI
import MapKit
@Observable
class PlaceSearchManager {
var searchResults: [MKMapItem] = []
var isSearching = false
var searchText = ""
private var searchTask: Task<Void, Never>?
// Search with debounce
func search(query: String, in region: MKCoordinateRegion) {
searchTask?.cancel()
guard !query.isEmpty else {
searchResults = []
return
}
searchTask = Task {
// 300ms debounce
try? await Task.sleep(for: .milliseconds(300))
guard !Task.isCancelled else { return }
isSearching = true
let request = MKLocalSearch.Request()
request.naturalLanguageQuery = query
request.region = region
request.resultTypes = [.pointOfInterest, .address]
let search = MKLocalSearch(request: request)
do {
let response = try await search.start()
if !Task.isCancelled {
searchResults = response.mapItems
}
} catch {
print("Search error: \(error.localizedDescription)")
searchResults = []
}
isSearching = false
}
}
func clearResults() {
searchResults = []
searchText = ""
}
}
struct SearchableMapView: View {
@State private var searchManager = PlaceSearchManager()
@State private var position: MapCameraPosition = .region(
MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 48.8566, longitude: 2.3522),
span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
)
)
@State private var selectedItem: MKMapItem?
@State private var visibleRegion: MKCoordinateRegion?
var body: some View {
NavigationStack {
Map(position: $position, selection: $selectedItem) {
// Display search results
ForEach(searchManager.searchResults, id: \.self) { item in
Marker(item: item)
}
}
.onMapCameraChange { context in
// Capture visible region for search
visibleRegion = context.region
}
.searchable(text: $searchManager.searchText, prompt: "Search for a place")
.onChange(of: searchManager.searchText) { _, newValue in
if let region = visibleRegion {
searchManager.search(query: newValue, in: region)
}
}
.overlay(alignment: .bottom) {
if let item = selectedItem {
PlaceDetailCard(item: item)
}
}
.navigationTitle("Map")
.navigationBarTitleDisplayMode(.inline)
}
}
}
struct PlaceDetailCard: View {
let item: MKMapItem
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(item.name ?? "Unknown Place")
.font(.headline)
if let address = item.placemark.title {
Text(address)
.font(.subheadline)
.foregroundStyle(.secondary)
}
HStack {
if let phone = item.phoneNumber {
Button {
if let url = URL(string: "tel:\(phone)") {
UIApplication.shared.open(url)
}
} label: {
Label("Call", systemImage: "phone")
}
.buttonStyle(.bordered)
}
Button {
item.openInMaps()
} label: {
Label("Directions", systemImage: "arrow.triangle.turn.up.right.diamond")
}
.buttonStyle(.borderedProminent)
}
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(.ultraThickMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
.padding()
}
}āļāļģāļāļēāļĄāļāļĩāđ 9: āļāļ°āđāļāļĨāļāļāļĩāđāļāļĒāļđāđāđāļāđāļāļāļīāļāļąāļāđāļāđāļāļĒāđāļēāļāđāļĢ (āļāļēāļĢāđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđ)?
āļāļēāļĢāđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđāđāļāļĨāļāļāļĩāđāļāļĒāļđāđāļāļĩāđāđāļāđāļāļāđāļāļāļ§āļēāļĄāđāļāđāļāļāļīāļāļąāļ GPS āļāļēāļĢāđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđāđāļāļāļĒāđāļāļāļāļĨāļąāļāļāļģāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāđāļāļāļīāļĻāļāļēāļāļāļĢāļāļāļąāļāļāđāļēāļĄ
import SwiftUI
import MapKit
import CoreLocation
@Observable
class GeocodingManager {
private let geocoder = CLGeocoder()
var coordinate: CLLocationCoordinate2D?
var address: String?
var isLoading = false
var error: String?
// Geocoding: address â coordinates
func geocode(address: String) async {
isLoading = true
error = nil
do {
let placemarks = try await geocoder.geocodeAddressString(address)
if let placemark = placemarks.first,
let location = placemark.location {
coordinate = location.coordinate
} else {
error = "Address not found"
}
} catch {
self.error = error.localizedDescription
}
isLoading = false
}
// Reverse geocoding: coordinates â address
func reverseGeocode(coordinate: CLLocationCoordinate2D) async {
isLoading = true
error = nil
let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
do {
let placemarks = try await geocoder.reverseGeocodeLocation(location)
if let placemark = placemarks.first {
address = formatAddress(placemark)
} else {
error = "Address not found"
}
} catch {
self.error = error.localizedDescription
}
isLoading = false
}
// Format readable address
private func formatAddress(_ placemark: CLPlacemark) -> String {
var components: [String] = []
if let street = placemark.thoroughfare {
if let number = placemark.subThoroughfare {
components.append("\(number) \(street)")
} else {
components.append(street)
}
}
if let city = placemark.locality {
components.append(city)
}
if let country = placemark.country {
components.append(country)
}
return components.joined(separator: ", ")
}
}
struct GeocodingDemoView: View {
@State private var manager = GeocodingManager()
@State private var addressInput = ""
@State private var position: MapCameraPosition = .automatic
var body: some View {
VStack {
// Address input field
HStack {
TextField("Enter an address", text: $addressInput)
.textFieldStyle(.roundedBorder)
Button("Search") {
Task {
await manager.geocode(address: addressInput)
if let coord = manager.coordinate {
position = .region(MKCoordinateRegion(
center: coord,
span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
))
}
}
}
.buttonStyle(.borderedProminent)
.disabled(addressInput.isEmpty || manager.isLoading)
}
.padding()
// Map with marker
Map(position: $position) {
if let coord = manager.coordinate {
Marker("Result", coordinate: coord)
.tint(.red)
}
}
if let error = manager.error {
Text(error)
.foregroundStyle(.red)
.padding()
}
}
}
}āļāļąāļ§āđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđāļāļāļ Apple āļĄāļĩāļāđāļāļāļģāļāļąāļāđāļāļāļēāļĢāļĢāđāļāļāļāļ āļŠāļģāļŦāļĢāļąāļāļāļĢāļīāļĄāļēāļāļāļĩāđāļŠāļđāļ āđāļāļ°āļāļģāđāļŦāđāđāļāđāđāļāļāđāļāđāļāļĢāļ·āđāļāļāļŦāļĢāļ·āļāļāļĢāļīāļāļēāļĢāļāļāļāļāļļāļāļāļĨāļāļĩāđāļŠāļēāļĄ āđāļāđāļ Mapbox āļŦāļĢāļ·āļ Google Maps
āļĢāļđāļāđāļāļāļāļąāđāļāļŠāļđāļāđāļĨāļ°āđāļāļ§āļāļāļīāļāļąāļāļīāļāļĩāđāļāļĩāļāļĩāđāļŠāļļāļ
āļāļģāļāļēāļĄāļāļĩāđ 10: āļāļ°āļāļĢāļąāļāļāļĢāļļāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļāđāļĄāļ·āđāļāļĄāļĩāđāļāļĢāļ·āđāļāļāļŦāļĄāļēāļĒāļāļģāļāļ§āļāļĄāļēāļāđāļāđāļāļĒāđāļēāļāđāļĢ?
āļāļēāļĢāđāļŠāļāļāđāļāļĢāļ·āđāļāļāļŦāļĄāļēāļĒāļŦāļĨāļēāļĒāļĢāđāļāļĒāļāļąāļāļāļēāļāļŠāđāļāļāļĨāļāļĢāļ°āļāļāļāđāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļ āļāļēāļĢāļāļąāļāļāļĨāļļāđāļĄāđāļĨāļ°āļāļēāļĢāđāļŦāļĨāļāļāļĩāļĨāļ°āļāđāļāļĒāđāļāđāļāļ§āļīāļāļĩāđāļāđāļāļąāļāļŦāļēāļāļĩāđāļĄāļĩāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļ
import SwiftUI
import MapKit
struct ClusteringMapView: View {
@State private var position: MapCameraPosition = .automatic
@State private var visiblePlaces: [Place] = []
@State private var visibleRegion: MKCoordinateRegion?
// All data (potentially thousands)
let allPlaces: [Place]
var body: some View {
Map(position: $position) {
// Display only visible places
ForEach(visiblePlaces) { place in
Marker(place.name, coordinate: place.coordinate)
}
}
.onMapCameraChange(frequency: .onEnd) { context in
// Update when user stops moving
visibleRegion = context.region
updateVisiblePlaces(in: context.region)
}
}
// Filter places in visible region
private func updateVisiblePlaces(in region: MKCoordinateRegion) {
let minLat = region.center.latitude - region.span.latitudeDelta / 2
let maxLat = region.center.latitude + region.span.latitudeDelta / 2
let minLon = region.center.longitude - region.span.longitudeDelta / 2
let maxLon = region.center.longitude + region.span.longitudeDelta / 2
// Spatial filtering
var filtered = allPlaces.filter { place in
place.coordinate.latitude >= minLat &&
place.coordinate.latitude <= maxLat &&
place.coordinate.longitude >= minLon &&
place.coordinate.longitude <= maxLon
}
// Limit number of displayed markers
if filtered.count > 100 {
// Sampling or clustering
filtered = Array(filtered.prefix(100))
}
visiblePlaces = filtered
}
}
// Simplified manual clustering
struct ClusteredPlace: Identifiable {
let id = UUID()
let coordinate: CLLocationCoordinate2D
let count: Int
let places: [Place]
var isCluster: Bool { count > 1 }
}
@Observable
class ClusterManager {
var clusters: [ClusteredPlace] = []
// Group nearby places based on zoom level
func cluster(places: [Place], in region: MKCoordinateRegion) {
let gridSize = region.span.latitudeDelta / 10
var grid: [String: [Place]] = [:]
for place in places {
// Grid key based on position
let gridX = Int(place.coordinate.longitude / gridSize)
let gridY = Int(place.coordinate.latitude / gridSize)
let key = "\(gridX),\(gridY)"
grid[key, default: []].append(place)
}
// Convert to clusters
clusters = grid.map { (_, places) in
let centerLat = places.map(\.coordinate.latitude).reduce(0, +) / Double(places.count)
let centerLon = places.map(\.coordinate.longitude).reduce(0, +) / Double(places.count)
return ClusteredPlace(
coordinate: CLLocationCoordinate2D(latitude: centerLat, longitude: centerLon),
count: places.count,
places: places
)
}
}
}
struct ClusterAnnotationView: View {
let cluster: ClusteredPlace
var body: some View {
if cluster.isCluster {
// Display a circle with count
ZStack {
Circle()
.fill(.blue)
.frame(width: 40, height: 40)
Text("\(cluster.count)")
.font(.system(size: 14, weight: .bold))
.foregroundStyle(.white)
}
} else {
// Simple marker
Image(systemName: "mappin.circle.fill")
.font(.title)
.foregroundStyle(.red)
}
}
}āļāļģāļāļēāļĄāļāļĩāđ 11: āļāļ°āļāļŠāļēāļāļĢāļ§āļĄ MapKit āļāļąāļāļāļĢāļīāļāļēāļĢāļāļ·āđāļ āđ āļāļāļ Apple āđāļāđāļāļĒāđāļēāļāđāļĢ?
MapKit āļāļŠāļēāļāļĢāļ§āļĄāļāļąāļāđāļāļĢāļĄāđāļ§āļīāļĢāđāļāļāļāļ Apple āļŦāļĨāļēāļĒāļāļąāļ§āđāļāļ·āđāļāļĄāļāļāļāļĢāļ°āļŠāļāļāļēāļĢāļāđāļāļĩāđāļāļĩāļāļķāđāļ āđāļāđāđāļāđ Look Around, CarPlay, WidgetKit
import SwiftUI
import MapKit
struct LookAroundMapView: View {
@State private var position: MapCameraPosition = .automatic
@State private var selectedPlace: Place?
@State private var lookAroundScene: MKLookAroundScene?
@State private var showLookAround = false
let places: [Place]
var body: some View {
Map(position: $position, selection: $selectedPlace) {
ForEach(places) { place in
Marker(place.name, coordinate: place.coordinate)
}
}
.onChange(of: selectedPlace) { _, newPlace in
if let place = newPlace {
Task {
await loadLookAroundScene(for: place.coordinate)
}
}
}
.sheet(isPresented: $showLookAround) {
if let scene = lookAroundScene {
LookAroundPreview(scene: scene)
.frame(height: 300)
}
}
.safeAreaInset(edge: .bottom) {
if selectedPlace != nil && lookAroundScene != nil {
Button("View in Look Around") {
showLookAround = true
}
.buttonStyle(.borderedProminent)
.padding()
}
}
}
// Load Look Around scene for a position
private func loadLookAroundScene(for coordinate: CLLocationCoordinate2D) async {
let request = MKLookAroundSceneRequest(coordinate: coordinate)
do {
lookAroundScene = try await request.scene
} catch {
lookAroundScene = nil
print("Look Around not available: \(error.localizedDescription)")
}
}
}
// Interactive Look Around component
struct LookAroundPreview: View {
let scene: MKLookAroundScene
@State private var isNavigating = false
var body: some View {
LookAroundPreviewRepresentable(scene: scene, isNavigating: $isNavigating)
.overlay(alignment: .topTrailing) {
Button {
isNavigating.toggle()
} label: {
Image(systemName: isNavigating ? "stop.fill" : "play.fill")
.padding()
.background(.ultraThinMaterial)
.clipShape(Circle())
}
.padding()
}
}
}
// UIViewRepresentable for Look Around
struct LookAroundPreviewRepresentable: UIViewRepresentable {
let scene: MKLookAroundScene
@Binding var isNavigating: Bool
func makeUIView(context: Context) -> MKLookAroundViewController {
let controller = MKLookAroundViewController(scene: scene)
controller.isNavigationEnabled = isNavigating
return controller
}
func updateUIView(_ uiView: MKLookAroundViewController, context: Context) {
uiView.isNavigationEnabled = isNavigating
}
}āļāļĢāđāļāļĄāļāļĩāđāļāļ°āļāļīāļāļīāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđ iOS āđāļĨāđāļ§āļŦāļĢāļ·āļāļĒāļąāļāļāļĢāļąāļ?
āļāļķāļāļāļāļāđāļ§āļĒāļāļąāļ§āļāļģāļĨāļāļāđāļāļāđāļāđāļāļāļ, flashcards āđāļĨāļ°āđāļāļāļāļāļŠāļāļāđāļāļāļāļīāļāļāļĢāļąāļ
āļāļāļŠāļĢāļļāļ
MapKit āļāļąāļ SwiftUI āļĄāļāļ API āļāļĩāđāļāļąāļāļŠāļĄāļąāļĒāđāļĨāļ°āļāļĢāļāļāļĨāļąāļāļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļāļŠāļēāļāļĢāļ§āļĄāđāļāļāļāļĩāđāđāļāđāļāļāļāļĨāļīāđāļāļāļąāļ iOS āļāļ§āļēāļĄāđāļāļĩāđāļĒāļ§āļāļēāļāđāļāļāļģāļāļāļīāļāļēāļĒāļāļĢāļ°āļāļāļ āļāļēāļĢāļāđāļāļāļāļąāļ āļāļēāļĢāļĢāļ°āļāļļāļāļģāđāļŦāļāđāļ āđāļĨāļ°āļāļēāļĢāļāđāļāļŦāļēāļŠāļāļēāļāļāļĩāđāļāļģāđāļŦāđāļāļąāļāļāļąāļāļāļē iOS āļāļĩāđāļĄāļĩāļāļĢāļ°āļŠāļāļāļēāļĢāļāđāđāļāļāđāļāđāļāđāļāļĢāļ°āļŦāļ§āđāļēāļāļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđāļāļēāļāđāļāļāļāļīāļ
āļĢāļēāļĒāļāļēāļĢāļāļĢāļ§āļāļŠāļāļ
- â
āđāļŠāļāļāđāļāļāļāļĩāđāļāđāļ§āļĒ
MapāđāļĨāļ°āļāļģāļŦāļāļāļāđāļēMapCameraPosition - â
āđāļāđāļĢāļđāļāđāļāļāđāļāļāļāļĩāđāļāđāļēāļ āđ (
standard,imagery,hybrid) - â
āđāļāļīāđāļĄ
MarkerāđāļĨāļ°AnnotationāđāļāļāļāļģāļŦāļāļāđāļāļ - â
āļāļąāļāļāļēāļĢāļāļēāļĢāļāļāļļāļāļēāļāļāļģāđāļŦāļāđāļāļāđāļ§āļĒ
CLLocationManager - â āļāļīāļāļāļēāļĄāļāļģāđāļŦāļāđāļāđāļāļāđāļĢāļĩāļĒāļĨāđāļāļĄāđāđāļĨāļ°āļ§āļēāļāđāļŠāđāļāļāļēāļ
- â
āļ§āļēāļāļāļēāļĢāļāđāļāļāļāļąāļ (
MapCircle,MapPolygon,MapPolyline) - â
āļāļģāļāļ§āļāđāļŠāđāļāļāļēāļāļāđāļ§āļĒ
MKDirections - â
āđāļāđāļāļēāļāļāļēāļĢāļāđāļāļŦāļēāļŠāļāļēāļāļāļĩāđāļāđāļ§āļĒ
MKLocalSearch - â āļāļģāđāļāļīāļāļāļēāļĢāđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđāđāļĨāļ°āđāļāđāļēāļĢāļŦāļąāļŠāļ āļđāļĄāļīāļĻāļēāļŠāļāļĢāđāđāļāļāļĒāđāļāļāļāļĨāļąāļ
- â āļāļĢāļąāļāļāļĢāļļāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļāļāđāļ§āļĒāļāļēāļĢāļāļąāļāļāļĨāļļāđāļĄāđāļāļĢāļ·āđāļāļāļŦāļĄāļēāļĒ
- â āļāļŠāļēāļāļĢāļ§āļĄ Look Around āđāļāļ·āđāļāļĄāļļāļĄāļĄāļāļāđāļāļāļāļ·āđāļĄāļāđāļģ
āđāļĢāļīāđāļĄāļāļķāļāļāđāļāļĄāđāļĨāļĒ!
āļāļāļŠāļāļāļāļ§āļēāļĄāļĢāļđāđāļāļāļāļāļļāļāļāđāļ§āļĒāļāļąāļ§āļāļģāļĨāļāļāļŠāļąāļĄāļ āļēāļĐāļāđāđāļĨāļ°āđāļāļāļāļāļŠāļāļāđāļāļāļāļīāļāļāļĢāļąāļ
āđāļāđāļ
āđāļāļĢāđ
āļāļāļāļ§āļēāļĄāļāļĩāđāđāļāļĩāđāļĒāļ§āļāđāļāļ

āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđ SwiftUI NavigationStack: āļĢāļđāļāđāļāļāļāļēāļĢāļāļģāļāļēāļ 2026
āđāļāļĢāļĩāļĒāļĄāļāļąāļ§āļŠāļąāļĄāļ āļēāļĐāļāđ iOS āļāđāļ§āļĒāļāļģāļāļēāļĄāļŠāļģāļāļąāļāđāļāļĩāđāļĒāļ§āļāļąāļ NavigationStack, NavigationPath āđāļĨāļ°āļĢāļđāļāđāļāļāļāļēāļĢāļāļģāļāļēāļāļŠāļĄāļąāļĒāđāļŦāļĄāđāđāļ SwiftUI

āļāļēāļĢāļŠāļąāļĄāļ āļēāļĐāļāđ StoreKit 2: āļāļēāļĢāļāļąāļāļāļēāļĢāļāļēāļĢāļŠāļĄāļąāļāļĢāļŠāļĄāļēāļāļīāļāđāļĨāļ°āļāļēāļĢāļāļĢāļ§āļāļŠāļāļāđāļāđāļŠāļĢāđāļ
āđāļāļĩāđāļĒāļ§āļāļēāļāļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđ iOS āđāļāļĩāđāļĒāļ§āļāļąāļ StoreKit 2 āļāļēāļĢāļāļąāļāļāļēāļĢāļāļēāļĢāļŠāļĄāļąāļāļĢāļŠāļĄāļēāļāļīāļ āļāļēāļĢāļāļĢāļ§āļāļŠāļāļāđāļāđāļŠāļĢāđāļ āđāļĨāļ°āļāļēāļĢāļāļģāļāļēāļĢāļāļ·āđāļāđāļāđāļāļāđāļāđāļāđ āļāļĢāđāļāļĄāļāļąāļ§āļāļĒāđāļēāļāđāļāđāļ Swift āļāļĩāđāđāļāđāļāļēāļāđāļāđāļāļĢāļīāļ

Vision Framework āđāļĨāļ° CoreML: āļāļģāļāļēāļĄāļŠāļąāļĄāļ āļēāļĐāļāđ iOS āđāļĢāļ·āđāļāļ ML āļāļāļāļļāļāļāļĢāļāđ
āđāļāļĢāļĩāļĒāļĄāļāļąāļ§āļŠāļąāļĄāļ āļēāļĐāļāđ iOS āļāđāļ§āļĒāļāļģāļāļēāļĄāļŠāļģāļāļąāļāđāļāļĩāđāļĒāļ§āļāļąāļ Vision Framework āđāļĨāļ° CoreML: āļāļēāļĢāļĢāļđāđāļāļģāļ āļēāļ āļāļēāļĢāļāļĢāļ§āļāļāļąāļāļ§āļąāļāļāļļ āđāļĨāļ° ML āļāļāļāļļāļāļāļĢāļāđ