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
...
我在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
...