SwiftUIを使用して現在位置を取得しようとしています。コードの下で、didUpdateLocationsデリゲートで初期化できませんでした。
class GetLocation : BindableObject {
var didChange = PassthroughSubject<GetLocation,Never>()
var location : CLLocation {
didSet {
didChange.send(self)
}
}
init() {}
}
以下のコードは機能します(本番環境では使用できません)。 CLLocationManagerDelegate
の実装は問題なく機能し、lastKnownLocation
はそれに応じて更新されます。
Info.plist
にNSLocationWhenInUseUsageDescription
を設定することを忘れないでください
class LocationManager: NSObject, CLLocationManagerDelegate, BindableObject {
private let manager: CLLocationManager
var didChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
didSet {
didChange.send(self)
}
}
init(manager: CLLocationManager = CLLocationManager()) {
self.manager = manager
super.init()
}
func startUpdating() {
self.manager.delegate = self
self.manager.requestWhenInUseAuthorization()
self.manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
lastKnownLocation = locations.last
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.startUpdatingLocation()
}
}
}
Xcode 11ベータ4以降、didChange
をwillChange
に変更する必要があります。
var willChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
willSet {
willChange.send(self)
}
}
私は1つのファイルを記述しましたSwiftの使用方法が記載されたパッケージ https://github.com/himbeles/LocationProvider 。これはObservableObject
を提供しますCLLocationManagerとそのデリゲートの-typeラッパークラス。SwiftUIで直接使用できる公開されたプロパティlocation
と、Combine経由でサブスクライブできるPassthroughSubjectがあります。両方のdidUpdateLocations
CLLocationManagerのイベント。
また、位置情報へのアクセスが以前に拒否された場合の処理も行います。デフォルトの動作では、アプリの設定でアクセスを有効にするリクエストとそこへのリンクをユーザーに提示します。
SwiftUIでは、次のように使用します
import SwiftUI
import LocationProvider
struct ContentView: View {
@ObservedObject var locationProvider : LocationProvider
init() {
locationProvider = LocationProvider()
do {try locationProvider.start()}
catch {
print("No location access.")
locationProvider.requestAuthorization()
}
}
var body: some View {
VStack{
Text("latitude \(locationProvider.location?.coordinate.latitude ?? 0)")
Text("longitude \(locationProvider.location?.coordinate.longitude ?? 0)")
}
}
}