SwiftUI navigationBarItems 两次调用位置权限

SwfitUI navigationBarItems calls location permission twice

我在navigationBarItems下创建了一个按钮,这个按钮打开一个新的sheet,新的sheet会弹出一个window询问用户位置。但是,在新的sheet中,CLLocationManager()被调用了两次,定位权限弹窗window会在几秒后消失。当你创建一个常规按钮时,弹出的位置 windown 将一直留在那里,直到你 select 选择其中一个,并且 CLLocationManager() 只会被调用一次。

代码

ConentView.swift

import SwiftUI

struct ContentView: View {


    @State var show = false
    @State var showEditPage = false

    var body: some View {


        NavigationView {
            List {
                Text("Text")
                Button("Location button") {
                    print("Location button tapped")
                    self.show.toggle()
                }.sheet(isPresented: $show) {
                    NewPage()
                }
            }
            .navigationBarItems(

                trailing:
                VStack {

                    Button(action: {
                        print("BarItemButton tapped")
                        self.showEditPage.toggle()
                    }) {
                        //Top right icon
                        Text("BarItemButton")
                    }.sheet(isPresented: $showEditPage) {
                        //Open sheet page
                        NewPage()
                    }

                }//End of trailing VStack
            )

        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

NewPage.swift

import SwiftUI

struct NewPage: View {

    @ObservedObject var locationManager = LocationManager()

    var body: some View {

        Text("New Page")


    }
}

struct NewPage_Previews: PreviewProvider {
    static var previews: some View {
        NewPage()
    }
}

LocationManager.swift

import SwiftUI
import Foundation
import CoreLocation
import Combine

class LocationManager: NSObject, ObservableObject {

    private let locationManager = CLLocationManager()
    let objectWillChange = PassthroughSubject<Void, Never>()

    override init() {
        super.init()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest

        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()

        print("In LocationManger.swift @initi, this is called")
    }

    @Published var locationStatus: CLAuthorizationStatus? {
        willSet {
            objectWillChange.send()
        }
    }

    @Published var lastLocation: CLLocation? {
        willSet { objectWillChange.send() }
    }

}

extension LocationManager: CLLocationManagerDelegate {

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        self.locationStatus = status

        print("In LocationManger.swift @Func locationManager, Status is updaing")

    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        self.lastLocation = location
        print("Location is updating")

    }

}

GitHub

您可以随意下载该项目在您的笔记本电脑上试用以查看问题: Github Example Project

截图

以下是使其在您的代码中工作的可能方法的更改:

1) 使 LocationManager 只有一个

class LocationManager: NSObject, ObservableObject {

    static var defaultManager: LocationManager = {
        LocationManager()
    }()
    ...

2) 使用默认管理器而不是每次 SwiftUI 想要 create/copy 查看结构时都创建

struct NewPage: View {

    @ObservedObject var locationManager = LocationManager.defaultManager
    ...