![]()
Dieser Beitrag baut auf meinem vorherigen Artikel “Where is my iPhone” auf, indem er mehr Apple-Frameworks verwendet, um eine funktionierende App fuer iPhone und iPad zu erstellen.
Neben der Bestimmung des Geraetestandorts werde ich eine vollstaendige Datenfluss-Pipeline vom Datenursprung ueber die Persistenz bis zur Visualisierung darlegen.
Vier Apple-Frameworks werden in diesem Artikel behandelt:
- Core Location
- Combine
- Core Data
- SwiftUI
Die Reihenfolge, in der ich die Frameworks durchgehe, folgt dem Datenfluss.

Standortkoordinaten stammen aus Core Location und werden in einer Core Data-Datenbank gespeichert.
Die Verbindung zwischen diesen beiden ist ein Combine-Publisher, der Koordinaten von Core Location empfaengt und an Core Data sendet.
Schliesslich visualisiert eine SwiftUI-View - verknuepft mit Core Data - alle Koordinaten aus der Datenbank als blaue Punkte auf einer Karte.
![]()
Der vollstaendige Xcode-Workspace mit der voll funktionsfaehigen Anwendung kann hier heruntergeladen werden.
Core Location
Alles beginnt mit einer Instanz von CLLocationManager, die in der Klasse LocationPublisher instanziiert wird.
private let locationManager = CLLocationManager()
Weise ihr einen Delegaten zu - in diesem Fall den LocationPublisher.
self.locationManager.delegate = self
Um Standortaktualisierungen zu erhalten, implementiere die Delegatenmethode:
extension LocationPublisher: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
wrapped.send((longitude: location.coordinate.longitude, latitude: location.coordinate.latitude))
}
}
Die Standortkoordinaten werden an unseren Combine Publisher gesendet, der im naechsten Abschnitt beschrieben wird.
Bevor du die App startest, fuege die erforderlichen Schluessel zur Info.plist hinzu; andernfalls funktioniert das Standort-Tracking nicht.

Beim ersten Start wirst du gefragt, ob Location Tracker den Standort des Benutzers bestimmen darf.

Jetzt “schieben” wir die Koordinaten in die Datenbank. Wir tun dies mit einem Combine Publisher, der “automagisch” den CLLocationManager und Core Data verbindet.
Combine
Der LocationPublisher hat ein PassthroughSubject, das ein Tupel nimmt, dessen erstes Element die Laenge und dessen zweites Element die Breite der empfangenen Koordinate ist.
typealias Output = (longitude: Double, latitude: Double)
typealias Failure = Never
private let wrapped = PassthroughSubject<(Output), Failure>()
Wie wir im Abschnitt “Core Location” gesehen haben, wird immer wenn eine Koordinate in der Delegatenmethode locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) empfangen wird, diese an das PassthroughSubject gesendet.
wrapped.send((longitude: location.coordinate.longitude, latitude: location.coordinate.latitude))
Es ist Zeit fuer den LocationPublisher, in Aktion zu treten und ein Combine-Publisher zu werden. Dies ermoeglicht es anderen Klassen, die als Datensenken fungieren (Core Data, jemand?), sich darauf zu abonnieren.
extension LocationPublisher: Publisher {
func receive<Downstream: Subscriber>(subscriber: Downstream) where Failure Downstream.Failure, Output Downstream.Input {
wrapped.subscribe(subscriber)
}
}
Dieser Code enthaelt alles, was noetig ist, um eine Methode zu implementieren, die die an das PassthroughSubject gesendeten Koordinaten empfaengt.
locationPublisher.sink(receiveValue:)
Dies ist wichtig fuer den naechsten Schritt, wenn wir die Ausgabe des LocationPublisher mit unserer Core Data-Datenbank verbinden.
Core Data
Um Standortdaten in die Datenbank zu “schieben”, muessen sowohl der LocationPublisher als auch Core Data verbunden werden.
Der PersistenceController ist die Klasse, die unseren gesamten datenbankbezogenen Code verarbeitet.
Sie hat eine Methode add, die ein (longitude, latitude)-Tupel nimmt und es in der Datenbank speichert.
Dieses Tupel wird in eine Location-Entitaet umgewandelt, die in LocationTracker.xcdatamodel definiert ist.

Die Verknuepfung des LocationPublisher und des PersistenceController erfordert nur eine Zeile, dank Combine.
locationPublisher.sink(receiveValue: PersistenceController.shared.add)
Dies geschieht gleich zu Beginn, wenn die Anwendung in LocationTrackerApp.init initialisiert wird.
Jetzt, da die Standortdaten in unsere Datenbank geschoben werden, wie werden sie auf einer Karte visualisiert?
Weiter zum naechsten Kapitel…
SwiftUI
Die Benutzeroberflaeche enthaelt eine Karte und einen Button.
Die Karte zeigt alle in CoreData gespeicherten Koordinaten an.
Das Druecken des Buttons loescht alle Daten in der Datenbank und entfernt automatisch die Markierungen von der Karte.
In ContentView werden die Standorte automatisch mit einem @FetchRequest aktualisiert.
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Location.timestamp, ascending: true)],
animation:.default)
private var locations: FetchedResults<Location>
Alles, was noch zu tun ist, ist der Karte zu sagen, dass sie locations verwenden soll.
Map(coordinateRegion: $region,
interactionModes:.all,
showsUserLocation: false,
userTrackingMode:.constant(.follow),
annotationItems: locations) { location in
MapAnnotation(coordinate: CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)) {
Circle().fill(Color.blue).frame(width: 10, height: 10)
}
}
Als Ergebnis wird jeder Standort als blauer Punkt angezeigt, und die Karte bleibt mit der Datenbank synchron. Kein weiterer Code erforderlich - ernsthaft.
Fazit
Das war’s in etwa fuer den Bau eines Standort-Trackers mit Apples neuesten Frameworks.
Ich hoffe, du hast dieses Tutorial genossen und einige hilfreiche Ideen fuer dein Projekt gewonnen.
Wenn du eine fertige Loesung bevorzugst, kann der vollstaendige Xcode-Workspace mit der voll funktionsfaehigen Anwendung hier heruntergeladen werden.