【问题标题】:SwfitUI navigationBarItems calls location permission twiceSwiftUI navigationBarItems 两次调用位置权限
【发布时间】:2019-12-20 21:39:10
【问题描述】:

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

截图

【问题讨论】:

  • 请发布您的代码,而不是期望人们下载 Xcode 项目。
  • 嗨@creeperspeak,更新文本代码

标签: swift xcode navigation uinavigationbar swiftui


【解决方案1】:

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

1) 让 LocationManager 成为唯一的一个

class LocationManager: NSObject, ObservableObject {

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

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

struct NewPage: View {

    @ObservedObject var locationManager = LocationManager.defaultManager
    ...

【讨论】:

  • 嗨@Asperi,非常感谢您的回答。它运作良好。我正忙于其他项目,所以忘了检查这个问题。请问你为什么要提出这个解决方案?静态如何帮助解决这个问题?我真的不明白它背后的逻辑。请随时在这里与我们分享,在此先感谢。
猜你喜欢
  • 1970-01-01
  • 2021-01-25
  • 1970-01-01
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 2021-01-31
  • 2020-11-14
  • 2017-09-13
相关资源
最近更新 更多