简体   繁体   中英

How can I call an API with user's current location on app launch in SwiftUI?

I'm trying to call an API on app launch with user's current location. My current code is:

In ContentView.swift :

struct ContentView: View {
    
    @StateObject var locationManager = LocationManager()
    
    var userLocation: String {
        let latitude = "\(locationManager.lastLocation?.coordinate.latitude ?? 0)"
        let longitude = "\(locationManager.lastLocation?.coordinate.longitude ?? 0)"
        return "\(latitude),\(longitude)"
    }
    
    @ObservedObject var api = randomAPI(location: userLocation)

    var body: some View {
        ...

In randomAPI.swift :

class randomAPI: ObservableObject {
    
    init(location: String) {
        callAPI(userLocation: location)
    }
    
    func callAPI(userLocation: String) {
        ...

And I'm getting the error:
Cannot use instance member 'userLocation' within property initializer; property initializers run before 'self' is available.

I don't know where should I put the line below to initialize the randomAPI. (I actually don't even know if this is the correct way to initialize it LOL)

@ObservedObject var api = randomAPI(location: userLocation)

Could someone help me with the problem? Thanks!

As Joakim mentioned, you need to use .onAppear . This is due to the fact that you cannot access a property before it is set in a struct.

For your case, the code would look like this:

struct ContentView: View {
    
    @StateObject var locationManager = LocationManager()
    
    var userLocation: String {
        let latitude = "\(locationManager.lastLocation?.coordinate.latitude ?? 0)"
        let longitude = "\(locationManager.lastLocation?.coordinate.longitude ?? 0)"
        return "\(latitude),\(longitude)"
    }
    
    @ObservedObject var api: randomAPI?

    var body: some View {
        SomeView()
            .onAppear {
                api = randomAPI(location: userLocation)
            }
...

However, I don't think setting an ObservedObject right after the view appears is the best way to do this.

If I were you, I would remove the init method in the rapidAPI class:

class randomAPI: ObservableObject {
    func callAPI(userLocation: String) {
        ...

And call the callAPI method when the view appears:

struct ContentView: View {
    
    @StateObject var locationManager = LocationManager()
    
    var userLocation: String {
        let latitude = "\(locationManager.lastLocation?.coordinate.latitude ?? 0)"
        let longitude = "\(locationManager.lastLocation?.coordinate.longitude ?? 0)"
        return "\(latitude),\(longitude)"
    }
    
    @ObservedObject var api = randomAPI()

    var body: some View {
        SomeView()
            .onAppear {
                api.callAPI(location: userLocation)
            }
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM