TL;DR
I made a sample delegate using SDK etc. written in Objective-C with reference to CoreLocation. Click here for the source> https://github.com/dropcontrol/LocationUpdata
I also use @ ObservableObject
and @ObserbedObject
instead of @State
as a method using Property Wrapper of SwiftUI. Actually, since Property is changed in a single View, @State
is enough. When using @ ObservableObject
, it means that Property needs to be changed across multiple Views.
reference:
https://rusutikaa.github.io/docs/developer.apple.com/documentation/swiftui/managing-model-data-in-your-app.html
https://capibara1969.com/2508/
The app itself is a single-function app that uses MapKit to get the latitude and longitude and display it. And, the part to get the latitude and longitude is done by func locationManager (_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
, which is defined in CLLocationManagerDelegate. So how do you write a delegate?
struct ContentView: View {
@ObservedObject var placeInfo = PlaceInfo()
var manager = CLLocationManager()
var managerDelegate = locationDelegate()
var body: some View {
VStack{
HStack {
Text("Latitude:")
Text(placeInfo.latitude)
}
HStack {
Text("longitude:")
Text(placeInfo.longitude)
}
Button(action: {
print("Button Tapped")
placeInfo.latitude = managerDelegate.currentLatitude
placeInfo.longitude = managerDelegate.currentLongitude
}){
Text("Current Location")
}
}
.onAppear() {
manager.delegate = managerDelegate
managerDelegate.locationManagerDidChangeAuthorization(manager)
}
}
}
As
var manager
of CLLocationManager ()var managerDelegate
of LocationDelegate ()manager.delegate = managerDeleagte
in .onAppear ()You can now access the managerDelegate.locationManagerDidChangeAuthorization (manager)
inside the Button and the managerDelegate.locationManagerDidChangeAuthorization (manager)
in .onAppear ().
The delegate itself is described as follows.
class locationDelegate : NSObject, ObservableObject, CLLocationManagerDelegate {
//Variables to retrieve from delegate
var currentLatitude: String = "none"
var currentLongitude: String = "none"
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .authorizedWhenInUse {
print("authorized")
manager.startUpdatingLocation()
// add "Privacy - Location Default Accuracy Reduced" in info.plist
// and edit in souce code that value is <true/> or <false/>
if manager.accuracyAuthorization != .fullAccuracy {
print("reduce accuracy")
// add "Privacy - Location Temporary Usage Description Dictionary" in info.plist
// and set "Location" in Key
manager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: "Location") {
(err) in
if err != nil {
print(err!)
return
}
}
}
} else {
print("not authorized")
// add "Privacy - Location When In Use Usage Description" in info.plist
manager.requestWhenInUseAuthorization()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
print(String(format: "%+.06f", location.coordinate.latitude))
print(String(format: "%+.06f", location.coordinate.longitude))
currentLatitude = String(format: "%+.06f", location.coordinate.latitude)
currentLongitude = String(format: "%+.06f", location.coordinate.longitude)
}
}
}
The above managerDelegate.locationManagerDidChangeAuthorization (manager)
is a method of CoreLocationg that alerts the user to license the location information (the location information cannot be obtained unless it passes there). Defined in func locationManagerDidChangeAuthorization (_ manager: CLLocationManager) {}
. At what level and how do you get permission to acquire information by setting in info.plist? You can set the.
The following func locationManager (_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {}
is used to update the location information. This is the delegate function. In fact, this function isn't called from anywhere, it's called every time the location is updated.
@ ObservableObject
and @ObserbedObject
As I wrote briefly, there is no problem writing Property Wrapper with @State
in this app (I also commented it out in the source), but with @ ObservableObject
, it is @Publised By attaching
to a variable, the update is automatically reflected, the variable is shared across multiple views, and it is applied in one place.
@ObservableObject
is defined as a class as follows.
class PlaceInfo: ObservableObject {
@Published var latitude: String = "none"
@Published var longitude: String = "none"
}
If you mistakenly type @ ObservedObject
in automatic storage here, an error will occur (obviously, it tends to be done).
When using ...
@ObservedObject var placeInfo = PlaceInfo() //This is Observed.
You can instantiate it with and then call it and rewrite variables by doing something like placeInfo.latitude
. I personally think that this is a cleaner way to write than writing with @State
. It doesn't look like it's problematic to use in a single view, but if you want to manage the scope of variables, it's a good idea to use them properly.
Recommended Posts