2026'da MapKit SwiftUI Mülakatı: Açıklamalar, Kaplamalar ve Konum Belirleme
iOS mülakatları için SwiftUI ile MapKit'te uzmanlaşın: özel açıklamalar, kaplamalar, konum belirleme, yer arama ve Maps entegrasyon kalıpları.

Haritalar birçok iOS uygulamasında temel bir özellik olarak yer alır: teslimat, fitness, emlak ve konum tabanlı sosyal ağlar. iOS 17'den itibaren MapKit, harita entegrasyonunu önemli ölçüde basitleştiren native bir SwiftUI API'si sunmaktadır. İşe alım uzmanları teknik mülakatlarda bu yetkinlikleri düzenli olarak değerlendirmektedir.
Her soru, gerçek bir teknik mülakatın formatını yansıtır; ayrıntılı yanıtlar ve çalışan kod içerir. Kavramlar temel düzeyden ileri düzeye doğru ilerler.
SwiftUI'de Harita Temelleri
Soru 1: SwiftUI ile temel bir harita nasıl gösterilir?
iOS 17'den itibaren SwiftUI, önceki UIViewRepresentable yaklaşımının yerini alan native Map bileşenini sunar. Map görünümü bir kamera konumu ve gösterilecek içerik kabul eder.
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 özelliği farklı modlara izin veren bir enum olan MapCameraPosition kullanır: .automatic (otomatik ayarlama), .region (sabit bölge), .camera (tam kontrol) veya .userLocation (kullanıcıya ortalanmış).
Soru 2: Mevcut farklı harita stilleri nelerdir?
MapKit, farklı kullanım durumlarına uygun çeşitli harita stilleri sunar. .mapStyle() modifier'ı haritanın görsel görünümünü yapılandırır.
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 stili, gösterilen kategorileri filtrelemek için bir pointsOfInterest parametresi kabul eder: .including([.restaurant, .cafe]) veya .excluding([.nightlife]).
Soru 3: Haritaya işaretçiler ve açıklamalar nasıl eklenir?
İşaretçiler haritada ilgi noktalarını temsil eder. SwiftUI MapKit çeşitli türler sunar: Marker (standart pin), Annotation (özel görünüm) ve MapCircle/MapPolygon (geometrik şekiller).
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)
}
}Temel fark: Marker native Apple Maps render'ını (standart pin) kullanırken, Annotation herhangi bir SwiftUI görünümüyle tam özelleştirmeye olanak tanır.
Konum Belirleme ve İzinler
Soru 4: Konum izinleri nasıl yönetilir ve kullanıcı konumu nasıl gösterilir?
Konum belirleme açık izinler ve farklı yetkilendirme durumlarının doğru şekilde ele alınmasını gerektirir. CLLocationManager izin isteklerini yönetir.
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 ve/veya NSLocationAlwaysUsageDescription anahtarları, konum kullanımının net bir açıklamasıyla Info.plist'te tanımlanmalıdır.
Soru 5: Gerçek zamanlı konum nasıl izlenir ve bir rota nasıl çizilir?
Gerçek zamanlı izleme, fitness veya navigasyon uygulamaları için kritik önemdedir. Bu soru, sürekli konum verisi akışını yönetme becerisini sınar.
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 mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Kaplamalar ve Geometrik Şekiller
Soru 6: Haritaya özel kaplamalar nasıl çizilir?
Kaplamalar, harita üzerinde bölgeler, rotalar veya alanlar göstermeye olanak tanır. SwiftUI MapKit MapCircle, MapPolygon ve MapPolyline sunar.
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)
}
}
}Soru 7: İki nokta arasında bir rota nasıl gösterilir?
Rota hesaplama, Apple sunucularından yol almak için MKDirections kullanır. Görüntüleme daha sonra MapPolyline ile yapılır.
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"
}
}
}Yer Arama ve Coğrafi Kodlama
Soru 8: MKLocalSearch ile yer arama nasıl uygulanır?
MKLocalSearch, ilgi noktaları, adresler veya işletmeler için arama yapmaya olanak tanır. Bu özellik, konum bazlı arama çubuğu olan uygulamalar için temel önemdedir.
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()
}
}Soru 9: Bir adres koordinatlara nasıl dönüştürülür (coğrafi kodlama)?
Coğrafi kodlama, bir metin adresini GPS koordinatlarına dönüştürür. Ters coğrafi kodlama ise bunun tersini gerçekleştirir.
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'ın coğrafi kodlayıcısı istek limitleri uygular. Yüksek hacimler için yerel önbellek ya da Mapbox veya Google Maps gibi üçüncü taraf hizmetler önerilir.
İleri Seviye Kalıplar ve En İyi Uygulamalar
Soru 10: Çok sayıda işaretçi ile performans nasıl optimize edilir?
Yüzlerce işaretçi göstermek performansı etkileyebilir. Kümeleme ve aşamalı yükleme etkili çözümlerdir.
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)
}
}
}Soru 11: MapKit diğer Apple servisleriyle nasıl entegre edilir?
MapKit, zenginleştirilmiş bir deneyim sunmak için çeşitli Apple framework'leri ile entegre olur: 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 mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Sonuç
SwiftUI ile MapKit, iOS uygulamalarına harita entegrasyonu için modern ve güçlü bir API sağlar. Açıklamalar, kaplamalar, konum belirleme ve yer arama konusundaki ustalık, teknik mülakatlarda deneyimli iOS geliştiricilerini öne çıkarır.
Gözden Geçirme Listesi
- ✅
Mapile harita göstermek veMapCameraPositionyapılandırmak - ✅ Farklı harita stillerini kullanmak (
standard,imagery,hybrid) - ✅ Özel
MarkerveAnnotationeklemek - ✅
CLLocationManagerile konum izinlerini yönetmek - ✅ Gerçek zamanlı konumu izlemek ve rota çizmek
- ✅ Kaplamalar çizmek (
MapCircle,MapPolygon,MapPolyline) - ✅
MKDirectionsile rotaları hesaplamak - ✅
MKLocalSearchile yer arama uygulamak - ✅ Coğrafi kodlama ve ters coğrafi kodlama yapmak
- ✅ İşaretçi kümeleme ile performansı optimize etmek
- ✅ İmmersif görünüm için Look Around entegre etmek
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
Etiketler
Paylaş
İlgili makaleler

SwiftUI NavigationStack mülakat soruları: Navigasyon kalıpları 2026
iOS mülakatları için NavigationStack, NavigationPath ve modern SwiftUI navigasyon kalıpları üzerine temel sorularla hazırlık.

StoreKit 2 Mülakatı: Abonelik Yönetimi ve Makbuz Doğrulama
StoreKit 2, abonelik yönetimi, makbuz doğrulama ve uygulama içi satın alma uygulaması hakkında iOS mülakat sorularında pratik Swift kod örnekleriyle uzmanlaşın.

Vision Framework ve CoreML: cihaz üzerinde ML için iOS mülakat soruları
Cihaz üzerinde makine öğrenmesi hakkında iOS mülakat soruları: görüntü tanıma, nesne algılama ve Vision Framework ile CoreML detaylı anlatımı.