mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-09-10 20:02:02 +02:00
WIP
This commit is contained in:
@@ -13,51 +13,58 @@ extension Modern.PlacemarksDemo {
|
||||
|
||||
// MARK: Geocoder
|
||||
|
||||
@MainActor
|
||||
final class Geocoder {
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
func geocode(
|
||||
place: ObjectSnapshot<Modern.PlacemarksDemo.Place>,
|
||||
completion: @escaping (_ title: String?, _ subtitle: String?) -> Void
|
||||
) {
|
||||
place: ObjectSnapshot<Modern.PlacemarksDemo.Place>
|
||||
) async -> (title: String?, subtitle: String?) {
|
||||
|
||||
self.geocoder?.cancelGeocode()
|
||||
|
||||
let geocoder = CLGeocoder()
|
||||
self.geocoder = geocoder
|
||||
geocoder.reverseGeocodeLocation(
|
||||
CLLocation(latitude: place.$latitude, longitude: place.$longitude),
|
||||
completionHandler: { (placemarks, error) -> Void in
|
||||
|
||||
defer {
|
||||
|
||||
self.geocoder = nil
|
||||
}
|
||||
guard let placemark = placemarks?.first else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let address = CNMutablePostalAddress()
|
||||
address.street = placemark.thoroughfare ?? ""
|
||||
address.subLocality = placemark.subThoroughfare ?? ""
|
||||
address.city = placemark.locality ?? ""
|
||||
address.subAdministrativeArea = placemark.subAdministrativeArea ?? ""
|
||||
address.state = placemark.administrativeArea ?? ""
|
||||
address.postalCode = placemark.postalCode ?? ""
|
||||
address.country = placemark.country ?? ""
|
||||
address.isoCountryCode = placemark.isoCountryCode ?? ""
|
||||
|
||||
completion(
|
||||
placemark.name,
|
||||
CNPostalAddressFormatter.string(
|
||||
from: address,
|
||||
style: .mailingAddress
|
||||
)
|
||||
)
|
||||
|
||||
defer {
|
||||
|
||||
if self.geocoder === geocoder {
|
||||
self.geocoder = nil
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
do {
|
||||
let placemarks = try await geocoder.reverseGeocodeLocation(
|
||||
CLLocation(latitude: place.$latitude, longitude: place.$longitude)
|
||||
)
|
||||
guard let placemark = placemarks.first else {
|
||||
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
let address = CNMutablePostalAddress()
|
||||
address.street = placemark.thoroughfare ?? ""
|
||||
address.subLocality = placemark.subThoroughfare ?? ""
|
||||
address.city = placemark.locality ?? ""
|
||||
address.subAdministrativeArea = placemark.subAdministrativeArea ?? ""
|
||||
address.state = placemark.administrativeArea ?? ""
|
||||
address.postalCode = placemark.postalCode ?? ""
|
||||
address.country = placemark.country ?? ""
|
||||
address.isoCountryCode = placemark.isoCountryCode ?? ""
|
||||
|
||||
return (
|
||||
placemark.name,
|
||||
CNPostalAddressFormatter.string(
|
||||
from: address,
|
||||
style: .mailingAddress
|
||||
)
|
||||
)
|
||||
}
|
||||
catch {
|
||||
|
||||
return (nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||
|
||||
import CoreLocation
|
||||
import Combine
|
||||
import CoreStore
|
||||
import Foundation
|
||||
import MapKit
|
||||
@@ -14,7 +13,7 @@ import SwiftUI
|
||||
extension Modern.PlacemarksDemo {
|
||||
|
||||
// MARK: - Modern.PlacemarksDemo.MainView
|
||||
|
||||
|
||||
struct MainView: View {
|
||||
|
||||
/**
|
||||
@@ -38,7 +37,7 @@ extension Modern.PlacemarksDemo {
|
||||
- Important: `perform(synchronous:)` was used here for illustration purposes. In practice, `perform(asynchronous:completion:)` is the preferred transaction type as synchronous transactions are very likely to cause deadlocks.
|
||||
*/
|
||||
private func demoSynchronousTransaction() {
|
||||
|
||||
|
||||
_ = try? Modern.PlacemarksDemo.dataStack.perform(
|
||||
synchronous: { (transaction) in
|
||||
|
||||
@@ -68,41 +67,12 @@ extension Modern.PlacemarksDemo {
|
||||
print("Commit failed: \(error as Any)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
|
||||
@ObjectState(Modern.PlacemarksDemo.placePublisher)
|
||||
var place: ObjectSnapshot<Modern.PlacemarksDemo.Place>?
|
||||
|
||||
init() {
|
||||
|
||||
self.sinkCancellable = self.$place?.reactive.snapshot().sink(
|
||||
receiveCompletion: { _ in
|
||||
|
||||
// Deleted, do nothing
|
||||
},
|
||||
receiveValue: { [self] (snapshot) in
|
||||
|
||||
guard let snapshot = snapshot else {
|
||||
|
||||
return
|
||||
}
|
||||
self.geocoder.geocode(place: snapshot) { (title, subtitle) in
|
||||
|
||||
guard self.place == snapshot else {
|
||||
|
||||
return
|
||||
}
|
||||
self.demoUnsafeTransaction(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
for: snapshot
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
@@ -130,34 +100,41 @@ extension Modern.PlacemarksDemo {
|
||||
)
|
||||
}
|
||||
}
|
||||
.navigationBarTitle("Placemarks")
|
||||
.navigationBarItems(
|
||||
trailing: Button("Random") {
|
||||
.task(id: self.place.map({ "\($0.$latitude),\($0.$longitude)" })) {
|
||||
|
||||
guard let place = self.place else {
|
||||
|
||||
return
|
||||
}
|
||||
let geocoded = await self.geocoder.geocode(place: place)
|
||||
guard self.place?.objectID() == place.objectID() else {
|
||||
|
||||
return
|
||||
}
|
||||
guard geocoded.title != nil || geocoded.subtitle != nil else {
|
||||
|
||||
return
|
||||
}
|
||||
self.demoUnsafeTransaction(
|
||||
title: geocoded.title,
|
||||
subtitle: geocoded.subtitle,
|
||||
for: place
|
||||
)
|
||||
}
|
||||
.navigationTitle("Placemarks")
|
||||
.toolbar {
|
||||
|
||||
Button("Random") {
|
||||
|
||||
self.demoSynchronousTransaction()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var sinkCancellable: AnyCancellable?
|
||||
private let geocoder = Modern.PlacemarksDemo.Geocoder()
|
||||
@State
|
||||
private var geocoder = Modern.PlacemarksDemo.Geocoder()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct _Demo_Modern_PlacemarksDemo_MainView_Preview: PreviewProvider {
|
||||
|
||||
// MARK: PreviewProvider
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
Modern.PlacemarksDemo.MainView()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,8 +11,8 @@ extension Modern {
|
||||
// MARK: - Modern.PlacemarksDemo
|
||||
|
||||
/**
|
||||
Sample usages for `CoreStoreObject` transactions
|
||||
*/
|
||||
Sample usages for `CoreStoreObject` transactions
|
||||
*/
|
||||
enum PlacemarksDemo {
|
||||
|
||||
// MARK: Internal
|
||||
@@ -20,6 +20,7 @@ extension Modern {
|
||||
/**
|
||||
⭐️ Sample 1: Setting up the `DataStack` and storage
|
||||
*/
|
||||
@MainActor
|
||||
static let dataStack: DataStack = {
|
||||
|
||||
let dataStack = DataStack(
|
||||
@@ -45,7 +46,8 @@ extension Modern {
|
||||
)
|
||||
return dataStack
|
||||
}()
|
||||
|
||||
|
||||
@MainActor
|
||||
static let placePublisher: ObjectPublisher<Modern.PlacemarksDemo.Place> = {
|
||||
|
||||
let dataStack = Modern.PlacemarksDemo.dataStack
|
||||
|
||||
Reference in New Issue
Block a user