首页 > 解决方案 > SwfitUI navigationBarItems 两次调用位置权限

问题描述

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

代码

ContentView.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()
    }
}

新页面.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 示例项目

截屏

在此处输入图像描述

标签: swiftxcodenavigationuinavigationbarswiftui

解决方案


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

1)使LocationManager只有一个

class LocationManager: NSObject, ObservableObject {

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

2)使用默认管理器而不是每次 SwiftUI 想要创建/复制视图结构时创建

struct NewPage: View {

    @ObservedObject var locationManager = LocationManager.defaultManager
    ...

推荐阅读