Swift 3 - 存储用户位置并从不同的视图控制器调用它
Swift 3 - store the User Location and call it from different View Controllers
我是编程方面的新手,这是我的第一个应用程序,如果方法很糟糕,我们深表歉意。
我创建了一个辅助方法来获取用户位置,因为我需要从不同的视图控制器调用它,所以我认为这是一种更简洁的方法。但我不知道为什么现在不起作用(没有错误,它只是展示了欧洲的普遍看法)。但是当它在视图控制器中时,它工作得很好。
我从我正在学习的课程中获得了这种新方法,并且我一直在研究许多来源。我也检查了 但我还没有找到任何解决方案。
这是我在 GMSClient 文件中创建的方法。它将获取用户位置,但如果用户禁用此选项,它将显示默认位置(以柏林为中心):
extension GMSClient: CLLocationManagerDelegate {
//MARK: Initial Location: Berlin
func setDefaultInitialLocation(_ map: GMSMapView) {
let camera = GMSCameraPosition.camera(withLatitude: 52.520736, longitude: 13.409423, zoom: 8)
map.camera = camera
let initialLocation = CLLocationCoordinate2DMake(52.520736, 13.409423)
let marker = GMSMarker(position: initialLocation)
marker.title = "Berlin"
marker.map = map
}
//MARK: Get user location
func getUserLocation(_ map: GMSMapView,_ locationManager: CLLocationManager) {
var userLocation: String?
locationManager.requestWhenInUseAuthorization()
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
map.isMyLocationEnabled = true
map.settings.myLocationButton = true
} else {
setDefaultInitialLocation(map)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
map.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
//Store User Location
userLocation = "\(location.coordinate.latitude), \(location.coordinate.longitude)"
print("userLocation is: \((userLocation) ?? "No user Location")")
}
}
}
}
这个文件也有这个单例:
// MARK: Shared Instance
class func sharedInstance() -> GMSClient {
struct Singleton {
static var sharedInstance = GMSClient()
}
return Singleton.sharedInstance
}
然后我在我的视图控制器中这样调用它:
class MapViewController: UIViewController, CLLocationManagerDelegate {
// MARK: Outlets
@IBOutlet weak var mapView: GMSMapView!
// MARK: Properties
let locationManager = CLLocationManager()
var userLocation: String?
let locationManagerDelegate = GMSClient()
// MARK: Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = locationManagerDelegate
GMSClient.sharedInstance().getUserLocation(mapView, locationManager)
}
有人知道什么地方可能出错吗?
谢谢!
我猜问题出在这里,
self.locationManager.delegate = locationManagerDelegate
您创建了 GMSClient
的新实例,并将其保存在存储的 属性 中,并且该实例被设置为 CLLocationManager
的委托 属性。
你需要这样做,
self.locationManager.delegate = GMSClient.sharedInstance()
您需要这样做,因为您希望 GMSClient
的单例实例成为 CLLocationManager
的委托而不是新实例。这样你的单身人士 class 就会收到来自
CLLocationManager class.
要详细了解您的代码为何不起作用,我建议您阅读更多有关对象、实例、实例变量、单例、委托设计模式的内容。
按照 Paulw11 所说的,我找到了使用通知的更快解决方案。
从第一个视图控制器中的 LocationManager 委托方法发送通知:
class MapViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
} else {
initialLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
mapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
let userInfo : NSDictionary = ["location" : location]
NotificationCenter.default.post(name: NSNotification.Name("UserLocationNotification"), object: self, userInfo: userInfo as [NSObject : AnyObject])
}
}
}
将第二个视图控制器设置为观察者。这样我就可以存储 userLocation 并在以后将其用于搜索请求:
class NeighbourhoodPickerViewController: UIViewController, UITextFieldDelegate {
var userLocation: String?
var currentLocation: CLLocation!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(locationUpdateNotification), name: Notification.Name("UserLocationNotification"), object: nil)
}
func locationUpdateNotification(notification: NSNotification) {
if let userInfo = notification.userInfo?["location"] as? CLLocation {
self.currentLocation = userInfo
self.userLocation = "\(userInfo.coordinate.latitude), \(userInfo.coordinate.longitude)"
}
}
我是编程方面的新手,这是我的第一个应用程序,如果方法很糟糕,我们深表歉意。
我创建了一个辅助方法来获取用户位置,因为我需要从不同的视图控制器调用它,所以我认为这是一种更简洁的方法。但我不知道为什么现在不起作用(没有错误,它只是展示了欧洲的普遍看法)。但是当它在视图控制器中时,它工作得很好。
我从我正在学习的课程中获得了这种新方法,并且我一直在研究许多来源。我也检查了
这是我在 GMSClient 文件中创建的方法。它将获取用户位置,但如果用户禁用此选项,它将显示默认位置(以柏林为中心):
extension GMSClient: CLLocationManagerDelegate {
//MARK: Initial Location: Berlin
func setDefaultInitialLocation(_ map: GMSMapView) {
let camera = GMSCameraPosition.camera(withLatitude: 52.520736, longitude: 13.409423, zoom: 8)
map.camera = camera
let initialLocation = CLLocationCoordinate2DMake(52.520736, 13.409423)
let marker = GMSMarker(position: initialLocation)
marker.title = "Berlin"
marker.map = map
}
//MARK: Get user location
func getUserLocation(_ map: GMSMapView,_ locationManager: CLLocationManager) {
var userLocation: String?
locationManager.requestWhenInUseAuthorization()
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.startUpdatingLocation()
map.isMyLocationEnabled = true
map.settings.myLocationButton = true
} else {
setDefaultInitialLocation(map)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
map.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
//Store User Location
userLocation = "\(location.coordinate.latitude), \(location.coordinate.longitude)"
print("userLocation is: \((userLocation) ?? "No user Location")")
}
}
}
}
这个文件也有这个单例:
// MARK: Shared Instance
class func sharedInstance() -> GMSClient {
struct Singleton {
static var sharedInstance = GMSClient()
}
return Singleton.sharedInstance
}
然后我在我的视图控制器中这样调用它:
class MapViewController: UIViewController, CLLocationManagerDelegate {
// MARK: Outlets
@IBOutlet weak var mapView: GMSMapView!
// MARK: Properties
let locationManager = CLLocationManager()
var userLocation: String?
let locationManagerDelegate = GMSClient()
// MARK: Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = locationManagerDelegate
GMSClient.sharedInstance().getUserLocation(mapView, locationManager)
}
有人知道什么地方可能出错吗?
谢谢!
我猜问题出在这里,
self.locationManager.delegate = locationManagerDelegate
您创建了 GMSClient
的新实例,并将其保存在存储的 属性 中,并且该实例被设置为 CLLocationManager
的委托 属性。
你需要这样做,
self.locationManager.delegate = GMSClient.sharedInstance()
您需要这样做,因为您希望 GMSClient
的单例实例成为 CLLocationManager
的委托而不是新实例。这样你的单身人士 class 就会收到来自
CLLocationManager class.
要详细了解您的代码为何不起作用,我建议您阅读更多有关对象、实例、实例变量、单例、委托设计模式的内容。
按照 Paulw11 所说的,我找到了使用通知的更快解决方案。
从第一个视图控制器中的 LocationManager 委托方法发送通知:
class MapViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { if status == .authorizedWhenInUse { locationManager.startUpdatingLocation() mapView.isMyLocationEnabled = true mapView.settings.myLocationButton = true } else { initialLocation() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.first { mapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0) locationManager.stopUpdatingLocation() let userInfo : NSDictionary = ["location" : location] NotificationCenter.default.post(name: NSNotification.Name("UserLocationNotification"), object: self, userInfo: userInfo as [NSObject : AnyObject]) } } }
将第二个视图控制器设置为观察者。这样我就可以存储 userLocation 并在以后将其用于搜索请求:
class NeighbourhoodPickerViewController: UIViewController, UITextFieldDelegate { var userLocation: String? var currentLocation: CLLocation! override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(locationUpdateNotification), name: Notification.Name("UserLocationNotification"), object: nil) } func locationUpdateNotification(notification: NSNotification) { if let userInfo = notification.userInfo?["location"] as? CLLocation { self.currentLocation = userInfo self.userLocation = "\(userInfo.coordinate.latitude), \(userInfo.coordinate.longitude)" } }