斯威夫特3 - 存储用户的位置,并从不同的视图控制器
问题描述:
称它为我在编程很新,这是我的第一个应用程序,很抱歉,如果该方法是非常寒酸。斯威夫特3 - 存储用户的位置,并从不同的视图控制器
我创建了一个辅助方法来获取用户的位置,因为我需要,所以我认为这是做一个更清洁的方式,从不同的视图控制器调用它。但我不知道为什么现在不工作(没有错误,它只是显示了欧洲的一般看法)。但是当它在视图控制器内时,它工作得很好。
我从我在做的过程中这种新的方法,我已经在许多来源一直在研究。我也检查了this question,但我还没有找到任何解决方案。
这是我在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")")
}
}
}
}
这个文件也是这个singelton:
// 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
委托,而不是一个新的实例。这样,您的单身人士课程将接收来自 CLLocationManager类的回调。
要了解更多关于为什么你的代码是不工作,我建议你阅读更多关于对象,实例,实例变量,单身,委托设计模式。
答
继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]) } } }
-
设置第二视图控制器作为观察者。这样我可以存储用户位置并在以后使用它的搜索请求:
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)" } }
你嵌套你'getUserLocation'函数内部的委托功能。这不起作用。将它们移出。 – Paulw11
我之前曾尝试过并且确实奏效,但我想稍后创建一个完成处理程序,以获取Google地图Web搜索请求的用户位置。就像...'func getUserLocation(_ map:GMSMapView,_ locationManager:CLLocationManager,completionHandlerForUserLocation:@escaping(_ userLocation:String ?, _error:NSError?) - > Void)){'所以我不知道如何使用委托方法... – celiux
说实话,完成处理程序可能不是这里正确的模式。你可以使用NSNotification,或者你可以设置一个委托或者在一个属性中存储一个闭包。我可能会使用NSNotification,因为它允许您轻松通知多个观察者 – Paulw11