在 Combine 的 `assign(to:on:)` 主题中分配给 @State 不会导致视图更新
Assigning to @State in Combine's `assign(to:on:)` subject does not result in view update
我有一个地图视图,它有一个按钮,当按下该按钮时,地图应以用户当前位置为中心。我正在尝试使用 Swift 的 Combine 框架来实现这一点。我尝试通过添加一个名为 mapCenter
的 @State
属性 并在 Combine 的 assign(to:on:)
主题中分配给这个 属性 来解决这个问题,如下所示:
struct MapWithButtonView: View {
// What the current map view center should be.
@State var mapCenter = CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977)
// A subject whose `send(_:)` method is being called from within the CenterButton view to center the map on the user's location.
private var centerButtonTappedPublisher = PassthroughSubject<Bool, Never>()
// A publisher that turns a "center button tapped" event into a coordinate.
private var centerButtonTappedCoordinatePublisher: AnyPublisher<CLLocationCoordinate2D?, Never> {
centerButtonTappedPublisher
.map { _ in LocationManager.default.currentUserCoordinate }
.eraseToAnyPublisher()
}
private var coordinatePublisher: AnyPublisher<CLLocationCoordinate2D, Never> {
Publishers.Merge(LocationManager.default.$initialUserCoordinate, centerButtonTappedCoordinatePublisher)
.replaceNil(with: CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977))
.eraseToAnyPublisher()
}
private var cancellableSet: Set<AnyCancellable> = []
init() {
// This does not result in an update to the view... why not?
coordinatePublisher
.receive(on: RunLoop.main)
.handleEvents(receiveSubscription: { (subscription) in
print("Receive subscription")
}, receiveOutput: { output in
print("Received output: \(String(describing: output))")
}, receiveCompletion: { _ in
print("Receive completion")
}, receiveCancel: {
print("Receive cancel")
}, receiveRequest: { demand in
print("Receive request: \(demand)")
})
.assign(to: \.mapCenter, on: self)
.store(in: &cancellableSet)
}
var body: some View {
ZStack {
MapView(coordinate: mapCenter)
.edgesIgnoringSafeArea(.all)
CenterButton(buttonTappedPublisher: centerButtonTappedPublisher)
}
}
}
MapView
是一个 UIViewRepresentable
视图,看起来像这样:
struct MapView: UIViewRepresentable {
// The center of the map.
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView(frame: .zero)
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
CenterButton
是一个简单的按钮,如下所示:
struct CenterButton: View {
var buttonTappedPublisher: PassthroughSubject<Bool, Never>
var body: some View {
Button(action: {
self.buttonTappedPublisher.send(true)
}) {
Image(systemName: "location.fill")
.imageScale(.large)
.accessibility(label: Text("Center map"))
}
}
}
而 LocationManager
是一个 ObservableObject
,它发布了用户的当前位置和初始位置:
class LocationManager: NSObject, ObservableObject {
// The first location reported by the CLLocationManager.
@Published var initialUserCoordinate: CLLocationCoordinate2D?
// The latest location reported by the CLLocationManager.
@Published var currentUserCoordinate: CLLocationCoordinate2D?
private let locationManager = CLLocationManager()
static let `default` = LocationManager()
private override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = true
locationManager.activityType = .other
locationManager.requestWhenInUseAuthorization()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
NSLog("Location authorization status changed to '\(status == .authorizedAlways ? "authorizedAlways" : "authorizedWhenInUse")'")
enableLocationServices()
case .denied, .restricted:
NSLog("Location authorization status changed to '\(status == .denied ? "denied" : "restricted")'")
disableLocationServices()
case .notDetermined:
NSLog("Location authorization status changed to 'notDetermined'")
default:
NSLog("Location authorization status changed to unknown status '\(status)'")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// We are only interested in the user's most recent location.
guard let location = locations.last else { return }
// Use the location to update the location manager's published state.
let coordinate = location.coordinate
if initialUserCoordinate == nil {
initialUserCoordinate = coordinate
}
currentUserCoordinate = coordinate
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
NSLog("Location manager failed with error: \(error)")
}
// MARK: Helpers.
private func enableLocationServices() {
locationManager.startUpdatingLocation()
}
private func disableLocationServices() {
locationManager.stopUpdatingLocation()
}
}
不幸的是,上面的方法不起作用。点击 CenterButton
时,视图永远不会更新。我最终通过使用带有 @Published var mapCenter
属性 的 ObservableObject
视图模型对象解决了这个问题,但是我不知道为什么我使用 @State
的初始解决方案不起作用。像我上面那样更新 @State
有什么问题?
请注意,如果尝试重现此内容,您需要在 Info.plist
文件中添加 NSLocationWhenInUseUsageDescription
键,其值为 "This app needs access to your location" ,以便能够授予位置权限。
新答案:
好的,我是联合收割机的新手,但它并没有让我走,所以我试了又试……现在它可以工作了,即使在模拟器中也是如此。
问题是,您在 struct/Contentview 中完成了所有操作,而不是在单独的 class 中进行合并,后者发布了您想要更改的值。
看看这个:
class Model : ObservableObject {
@Published var mapCenter : CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0, longitude: 0)
// A subject whose `send(_:)` method is being called from within the CenterButton view to center the map on the user's location.
public var centerButtonTappedPublisher = PassthroughSubject<Bool, Never>()
// A publisher that turns a "center button tapped" event into a coordinate.
private var centerButtonTappedCoordinatePublisher: AnyPublisher<CLLocationCoordinate2D?, Never> {
centerButtonTappedPublisher
.map { _ in
print ("new loc in pub: ", LocationManager.default.currentUserCoordinate)
return LocationManager.default.currentUserCoordinate
}
.eraseToAnyPublisher()
}
private var coordinatePublisher: AnyPublisher<CLLocationCoordinate2D, Never> {
Publishers.Merge(LocationManager.default.$initialUserCoordinate, centerButtonTappedCoordinatePublisher)
.replaceNil(with: CLLocationCoordinate2D(latitude: 2.0, longitude: 2.0))
.eraseToAnyPublisher()
}
private var cancellableSet: Set<AnyCancellable> = []
var cancellable: AnyCancellable?
init() {
// This does not result in an update to the view... why not?
coordinatePublisher
.receive(on: RunLoop.main)
// .handleEvents(receiveSubscription: { (subscription) in
// print("Receive subscription")
// }, receiveOutput: { output in
// print("Received output: \(String(describing: output))")
//
// }, receiveCompletion: { _ in
// print("Receive completion")
// }, receiveCancel: {
// print("Receive cancel")
// }, receiveRequest: { demand in
// print("Receive request: \(demand)")
// })
.assign(to: \.mapCenter, on: self)
.store(in: &cancellableSet)
print(cancellableSet)
self.cancellable = self.coordinatePublisher.receive(on: DispatchQueue.main)
.assign(to: \.mapCenter, on: self)
}
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
MapView(coordinate: model.mapCenter)
.edgesIgnoringSafeArea(.all)
CenterButton(buttonTappedPublisher: model.centerButtonTappedPublisher)
}
}
}
struct MapView: UIViewRepresentable {
// The center of the map.
var coordinate: CLLocationCoordinate2D
let mapView = MKMapView(frame: .zero)
func makeUIView(context: Context) -> MKMapView {
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
print("map new coordinate", coordinate)
view.setRegion(region, animated: true)
}
}
class LocationManager: NSObject, ObservableObject {
// The first location reported by the CLLocationManager.
@Published var initialUserCoordinate: CLLocationCoordinate2D?
// The latest location reported by the CLLocationManager.
@Published var currentUserCoordinate: CLLocationCoordinate2D?
private let locationManager = CLLocationManager()
static let `default` = LocationManager()
private override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = true
locationManager.activityType = .other
locationManager.requestWhenInUseAuthorization()
enableLocationServices()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
NSLog("Location authorization status changed to '\(status == .authorizedAlways ? "authorizedAlways" : "authorizedWhenInUse")'")
()
case .denied, .restricted:
NSLog("Location authorization status changed to '\(status == .denied ? "denied" : "restricted")'")
disableLocationServices()
case .notDetermined:
NSLog("Location authorization status changed to 'notDetermined'")
default:
NSLog("Location authorization status changed to unknown status '\(status)'")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// We are only interested in the user's most recent location.
guard let location = locations.last else { return }
// Use the location to update the location manager's published state.
let coordinate = location.coordinate
if initialUserCoordinate == nil {
initialUserCoordinate = coordinate
}
currentUserCoordinate = coordinate
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
NSLog("Location manager failed with error: \(error)")
}
// MARK: Helpers.
public func enableLocationServices() {
locationManager.startUpdatingLocation()
}
private func disableLocationServices() {
locationManager.stopUpdatingLocation()
}
}
struct CenterButton: View {
var buttonTappedPublisher: PassthroughSubject<Bool, Never>
var body: some View {
Button(action: {
self.buttonTappedPublisher.send(true)
}) {
Image(systemName: "location.fill")
.imageScale(.large)
.accessibility(label: Text("Center map"))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
旧答案:
好的,因为你没有给我们一个可复制的可重现的例子,我做了一个简单的例子。随意复制并使用它来解决您的问题。
struct MapView: UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView(frame: .zero)
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 1.02, longitudeDelta: 1.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
struct ContentView: View {
@State var coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
var body: some View {
VStack {
Button(action: {
self.coordinate.latitude += 10
self.coordinate.longitude = 30
}) {
Text("new coordinate")
}
MapView(coordinate: coordinate)
}
}
}
是的,您的代码有效。试试这个:
var body: some View {
ZStack {
MapView(coordinate: mapCenter)
.edgesIgnoringSafeArea(.all)
CenterButton(buttonTappedPublisher: centerButtonTappedPublisher)
}.onAppear() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
self.mapCenter.latitude += 0.1
}
}
}
你会看到,地图在不断移动。
也许您在模拟器中尝试过您的代码?那里的用户位置永远不会改变,所以如果你再次点击你的按钮,什么也不会发生......在真实设备上尝试并开始移动;)
为此您不需要 CLLocationManager
,只需在您的 UIViewRepresentable
.
中像这样 map.userLocation.location.coordinate
访问当前用户注释
https://developer.apple.com/documentation/mapkit/mkuserlocation/1452415-location?language=objc
我有一个地图视图,它有一个按钮,当按下该按钮时,地图应以用户当前位置为中心。我正在尝试使用 Swift 的 Combine 框架来实现这一点。我尝试通过添加一个名为 mapCenter
的 @State
属性 并在 Combine 的 assign(to:on:)
主题中分配给这个 属性 来解决这个问题,如下所示:
struct MapWithButtonView: View {
// What the current map view center should be.
@State var mapCenter = CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977)
// A subject whose `send(_:)` method is being called from within the CenterButton view to center the map on the user's location.
private var centerButtonTappedPublisher = PassthroughSubject<Bool, Never>()
// A publisher that turns a "center button tapped" event into a coordinate.
private var centerButtonTappedCoordinatePublisher: AnyPublisher<CLLocationCoordinate2D?, Never> {
centerButtonTappedPublisher
.map { _ in LocationManager.default.currentUserCoordinate }
.eraseToAnyPublisher()
}
private var coordinatePublisher: AnyPublisher<CLLocationCoordinate2D, Never> {
Publishers.Merge(LocationManager.default.$initialUserCoordinate, centerButtonTappedCoordinatePublisher)
.replaceNil(with: CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977))
.eraseToAnyPublisher()
}
private var cancellableSet: Set<AnyCancellable> = []
init() {
// This does not result in an update to the view... why not?
coordinatePublisher
.receive(on: RunLoop.main)
.handleEvents(receiveSubscription: { (subscription) in
print("Receive subscription")
}, receiveOutput: { output in
print("Received output: \(String(describing: output))")
}, receiveCompletion: { _ in
print("Receive completion")
}, receiveCancel: {
print("Receive cancel")
}, receiveRequest: { demand in
print("Receive request: \(demand)")
})
.assign(to: \.mapCenter, on: self)
.store(in: &cancellableSet)
}
var body: some View {
ZStack {
MapView(coordinate: mapCenter)
.edgesIgnoringSafeArea(.all)
CenterButton(buttonTappedPublisher: centerButtonTappedPublisher)
}
}
}
MapView
是一个 UIViewRepresentable
视图,看起来像这样:
struct MapView: UIViewRepresentable {
// The center of the map.
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView(frame: .zero)
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
CenterButton
是一个简单的按钮,如下所示:
struct CenterButton: View {
var buttonTappedPublisher: PassthroughSubject<Bool, Never>
var body: some View {
Button(action: {
self.buttonTappedPublisher.send(true)
}) {
Image(systemName: "location.fill")
.imageScale(.large)
.accessibility(label: Text("Center map"))
}
}
}
而 LocationManager
是一个 ObservableObject
,它发布了用户的当前位置和初始位置:
class LocationManager: NSObject, ObservableObject {
// The first location reported by the CLLocationManager.
@Published var initialUserCoordinate: CLLocationCoordinate2D?
// The latest location reported by the CLLocationManager.
@Published var currentUserCoordinate: CLLocationCoordinate2D?
private let locationManager = CLLocationManager()
static let `default` = LocationManager()
private override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = true
locationManager.activityType = .other
locationManager.requestWhenInUseAuthorization()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
NSLog("Location authorization status changed to '\(status == .authorizedAlways ? "authorizedAlways" : "authorizedWhenInUse")'")
enableLocationServices()
case .denied, .restricted:
NSLog("Location authorization status changed to '\(status == .denied ? "denied" : "restricted")'")
disableLocationServices()
case .notDetermined:
NSLog("Location authorization status changed to 'notDetermined'")
default:
NSLog("Location authorization status changed to unknown status '\(status)'")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// We are only interested in the user's most recent location.
guard let location = locations.last else { return }
// Use the location to update the location manager's published state.
let coordinate = location.coordinate
if initialUserCoordinate == nil {
initialUserCoordinate = coordinate
}
currentUserCoordinate = coordinate
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
NSLog("Location manager failed with error: \(error)")
}
// MARK: Helpers.
private func enableLocationServices() {
locationManager.startUpdatingLocation()
}
private func disableLocationServices() {
locationManager.stopUpdatingLocation()
}
}
不幸的是,上面的方法不起作用。点击 CenterButton
时,视图永远不会更新。我最终通过使用带有 @Published var mapCenter
属性 的 ObservableObject
视图模型对象解决了这个问题,但是我不知道为什么我使用 @State
的初始解决方案不起作用。像我上面那样更新 @State
有什么问题?
请注意,如果尝试重现此内容,您需要在 Info.plist
文件中添加 NSLocationWhenInUseUsageDescription
键,其值为 "This app needs access to your location" ,以便能够授予位置权限。
新答案:
好的,我是联合收割机的新手,但它并没有让我走,所以我试了又试……现在它可以工作了,即使在模拟器中也是如此。
问题是,您在 struct/Contentview 中完成了所有操作,而不是在单独的 class 中进行合并,后者发布了您想要更改的值。
看看这个:
class Model : ObservableObject {
@Published var mapCenter : CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0, longitude: 0)
// A subject whose `send(_:)` method is being called from within the CenterButton view to center the map on the user's location.
public var centerButtonTappedPublisher = PassthroughSubject<Bool, Never>()
// A publisher that turns a "center button tapped" event into a coordinate.
private var centerButtonTappedCoordinatePublisher: AnyPublisher<CLLocationCoordinate2D?, Never> {
centerButtonTappedPublisher
.map { _ in
print ("new loc in pub: ", LocationManager.default.currentUserCoordinate)
return LocationManager.default.currentUserCoordinate
}
.eraseToAnyPublisher()
}
private var coordinatePublisher: AnyPublisher<CLLocationCoordinate2D, Never> {
Publishers.Merge(LocationManager.default.$initialUserCoordinate, centerButtonTappedCoordinatePublisher)
.replaceNil(with: CLLocationCoordinate2D(latitude: 2.0, longitude: 2.0))
.eraseToAnyPublisher()
}
private var cancellableSet: Set<AnyCancellable> = []
var cancellable: AnyCancellable?
init() {
// This does not result in an update to the view... why not?
coordinatePublisher
.receive(on: RunLoop.main)
// .handleEvents(receiveSubscription: { (subscription) in
// print("Receive subscription")
// }, receiveOutput: { output in
// print("Received output: \(String(describing: output))")
//
// }, receiveCompletion: { _ in
// print("Receive completion")
// }, receiveCancel: {
// print("Receive cancel")
// }, receiveRequest: { demand in
// print("Receive request: \(demand)")
// })
.assign(to: \.mapCenter, on: self)
.store(in: &cancellableSet)
print(cancellableSet)
self.cancellable = self.coordinatePublisher.receive(on: DispatchQueue.main)
.assign(to: \.mapCenter, on: self)
}
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
VStack {
MapView(coordinate: model.mapCenter)
.edgesIgnoringSafeArea(.all)
CenterButton(buttonTappedPublisher: model.centerButtonTappedPublisher)
}
}
}
struct MapView: UIViewRepresentable {
// The center of the map.
var coordinate: CLLocationCoordinate2D
let mapView = MKMapView(frame: .zero)
func makeUIView(context: Context) -> MKMapView {
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
print("map new coordinate", coordinate)
view.setRegion(region, animated: true)
}
}
class LocationManager: NSObject, ObservableObject {
// The first location reported by the CLLocationManager.
@Published var initialUserCoordinate: CLLocationCoordinate2D?
// The latest location reported by the CLLocationManager.
@Published var currentUserCoordinate: CLLocationCoordinate2D?
private let locationManager = CLLocationManager()
static let `default` = LocationManager()
private override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.pausesLocationUpdatesAutomatically = true
locationManager.activityType = .other
locationManager.requestWhenInUseAuthorization()
enableLocationServices()
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
NSLog("Location authorization status changed to '\(status == .authorizedAlways ? "authorizedAlways" : "authorizedWhenInUse")'")
()
case .denied, .restricted:
NSLog("Location authorization status changed to '\(status == .denied ? "denied" : "restricted")'")
disableLocationServices()
case .notDetermined:
NSLog("Location authorization status changed to 'notDetermined'")
default:
NSLog("Location authorization status changed to unknown status '\(status)'")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// We are only interested in the user's most recent location.
guard let location = locations.last else { return }
// Use the location to update the location manager's published state.
let coordinate = location.coordinate
if initialUserCoordinate == nil {
initialUserCoordinate = coordinate
}
currentUserCoordinate = coordinate
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
NSLog("Location manager failed with error: \(error)")
}
// MARK: Helpers.
public func enableLocationServices() {
locationManager.startUpdatingLocation()
}
private func disableLocationServices() {
locationManager.stopUpdatingLocation()
}
}
struct CenterButton: View {
var buttonTappedPublisher: PassthroughSubject<Bool, Never>
var body: some View {
Button(action: {
self.buttonTappedPublisher.send(true)
}) {
Image(systemName: "location.fill")
.imageScale(.large)
.accessibility(label: Text("Center map"))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
旧答案:
好的,因为你没有给我们一个可复制的可重现的例子,我做了一个简单的例子。随意复制并使用它来解决您的问题。
struct MapView: UIViewRepresentable {
var coordinate: CLLocationCoordinate2D
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView(frame: .zero)
mapView.showsUserLocation = true
return mapView
}
func updateUIView(_ view: MKMapView, context: Context) {
let span = MKCoordinateSpan(latitudeDelta: 1.02, longitudeDelta: 1.02)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
struct ContentView: View {
@State var coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
var body: some View {
VStack {
Button(action: {
self.coordinate.latitude += 10
self.coordinate.longitude = 30
}) {
Text("new coordinate")
}
MapView(coordinate: coordinate)
}
}
}
是的,您的代码有效。试试这个:
var body: some View {
ZStack {
MapView(coordinate: mapCenter)
.edgesIgnoringSafeArea(.all)
CenterButton(buttonTappedPublisher: centerButtonTappedPublisher)
}.onAppear() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
self.mapCenter.latitude += 0.1
}
}
}
你会看到,地图在不断移动。 也许您在模拟器中尝试过您的代码?那里的用户位置永远不会改变,所以如果你再次点击你的按钮,什么也不会发生......在真实设备上尝试并开始移动;)
为此您不需要 CLLocationManager
,只需在您的 UIViewRepresentable
.
map.userLocation.location.coordinate
访问当前用户注释
https://developer.apple.com/documentation/mapkit/mkuserlocation/1452415-location?language=objc