Swift 将坐标附加到数组并添加到地图
Swift Appending Coordinates into Array and Adding to Map
我的这个应用程序的目的是允许用户在选项卡控制器的一个选项卡中输入任何一组坐标,而在另一个选项卡中,坐标将被放置在带有注释的图钉中。
我一直在尝试实现的方法是使用一个全局数组,它附加输入坐标并在另一个 class 文件(使用 mapView)中调用。我在尝试遍历数组以放置引脚时遇到了很多问题,我不确定哪里出了问题。
输入信息class文件:
import UIKit
import CoreLocation
var locations: [Dictionary<String, Any>] = [] // here I initialize my array
class OtherVC: UIViewController {
@IBOutlet weak var latitudeField: UITextField!
@IBOutlet weak var longitudeField: UITextField!
@IBOutlet weak var titleTextField: UITextField!
var coordinates = [CLLocationCoordinate2D]()
override func viewDidLoad() {
super.viewDidLoad()
}
// This IBOutlet takes the coordinate input information from the user
@IBAction func addToMap(_ sender: Any) {
let lat = latitudeField.text!
let long = longitudeField.text!
let title = titleTextField.text!
var location: [String: Any] = ["title": title, "latitude": lat, "longitude": long]
locations.append(location) // adding the info to the array
let mapVC : MapViewController = MapViewController()
mapVC.iterateLocations()
}
}
MapView class 文件:
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
}
// this method here iterates through each of the locations in the array
func iterateLocations() -> Bool {
for location in locations {
var momentaryLat = (location["latitude"] as! NSString).doubleValue
var momentaryLong = (location["longitude"] as! NSString).doubleValue
let annotation = MKPointAnnotation()
annotation.title = location["title"] as? String
annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
mapView.addAnnotation(annotation)
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "pinAnnotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
}
annotationView?.annotation = annotation
return annotationView
}
}
第 "mapView.addAnnotation(annotation)" 行中弹出错误,提示在尝试解包 Optional 时发现 nil。所以我认为错误是信息没有保存在注释中,但我没有立即看出哪里错了。
欢迎使用可能更容易实施的此方法的任何替代方法!
1) 您实际上是在 addToMap
方法内创建一个具有局部作用域的新 MapViewController
。这个新的视图控制器是以编程方式创建的,与 UITabBarViewController
的 MapViewController
实例无关。它的 mapView
出口设置为 nil
,因此当您尝试访问该 属性 时,隐式解包将找到 nil
,导致您的应用程序崩溃。此外,视图控制器本地实例将在 addToMap
方法结束时被释放。
2) 因此,您要做的是通过 UITabBarController
获取对已经存在的 MapViewController
的访问权限。但是同样,如果您在用户切换到地图视图选项卡至少一次之前尝试访问 mapView
出口,您将看到同样的崩溃。这是因为 MapViewController
的视图不会被加载(视图仅在需要时从 nib 加载,即在这种情况下,当用户点击地图视图选项卡并且它变得可见时)。您可以强制加载视图,并通过调用 loadViewIfNeeded()
.
设置 mapView
插座
3) 每次调用 addToMap
时,您都将新位置附加到之前的位置,然后遍历所有位置以创建注释。这会导致相同的注释被多次添加到地图中。您可以将 iterateLocations
方法更改为 add(newLocation:[String:Any])
之类的方法,并只传递从用户输入中获得的最后一个位置。
所以一种解决方案是替换:
let mapVC : MapViewController = MapViewController()
里面 addToMap
有:
let mapVC : MapViewController = self.tabBarController!.viewControllers![1] as! MapViewController
mapVC.loadViewIfNeeded()
mapVC.add(newLocation:location)
假设 OtherVC
位于标签视图控制器的索引 0,MapViewController
位于索引 1。还有:
func add(newLocation location:[String:Any]) {
let momentaryLat = (location["latitude"] as! NSString).doubleValue
let momentaryLong = (location["longitude"] as! NSString).doubleValue
let annotation = MKPointAnnotation()
annotation.title = location["title"] as? String
annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
mapView.addAnnotation(annotation)
}
我的这个应用程序的目的是允许用户在选项卡控制器的一个选项卡中输入任何一组坐标,而在另一个选项卡中,坐标将被放置在带有注释的图钉中。
我一直在尝试实现的方法是使用一个全局数组,它附加输入坐标并在另一个 class 文件(使用 mapView)中调用。我在尝试遍历数组以放置引脚时遇到了很多问题,我不确定哪里出了问题。
输入信息class文件:
import UIKit
import CoreLocation
var locations: [Dictionary<String, Any>] = [] // here I initialize my array
class OtherVC: UIViewController {
@IBOutlet weak var latitudeField: UITextField!
@IBOutlet weak var longitudeField: UITextField!
@IBOutlet weak var titleTextField: UITextField!
var coordinates = [CLLocationCoordinate2D]()
override func viewDidLoad() {
super.viewDidLoad()
}
// This IBOutlet takes the coordinate input information from the user
@IBAction func addToMap(_ sender: Any) {
let lat = latitudeField.text!
let long = longitudeField.text!
let title = titleTextField.text!
var location: [String: Any] = ["title": title, "latitude": lat, "longitude": long]
locations.append(location) // adding the info to the array
let mapVC : MapViewController = MapViewController()
mapVC.iterateLocations()
}
}
MapView class 文件:
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
}
// this method here iterates through each of the locations in the array
func iterateLocations() -> Bool {
for location in locations {
var momentaryLat = (location["latitude"] as! NSString).doubleValue
var momentaryLong = (location["longitude"] as! NSString).doubleValue
let annotation = MKPointAnnotation()
annotation.title = location["title"] as? String
annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
mapView.addAnnotation(annotation)
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "pinAnnotation"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
}
annotationView?.annotation = annotation
return annotationView
}
}
第 "mapView.addAnnotation(annotation)" 行中弹出错误,提示在尝试解包 Optional 时发现 nil。所以我认为错误是信息没有保存在注释中,但我没有立即看出哪里错了。
欢迎使用可能更容易实施的此方法的任何替代方法!
1) 您实际上是在 addToMap
方法内创建一个具有局部作用域的新 MapViewController
。这个新的视图控制器是以编程方式创建的,与 UITabBarViewController
的 MapViewController
实例无关。它的 mapView
出口设置为 nil
,因此当您尝试访问该 属性 时,隐式解包将找到 nil
,导致您的应用程序崩溃。此外,视图控制器本地实例将在 addToMap
方法结束时被释放。
2) 因此,您要做的是通过 UITabBarController
获取对已经存在的 MapViewController
的访问权限。但是同样,如果您在用户切换到地图视图选项卡至少一次之前尝试访问 mapView
出口,您将看到同样的崩溃。这是因为 MapViewController
的视图不会被加载(视图仅在需要时从 nib 加载,即在这种情况下,当用户点击地图视图选项卡并且它变得可见时)。您可以强制加载视图,并通过调用 loadViewIfNeeded()
.
mapView
插座
3) 每次调用 addToMap
时,您都将新位置附加到之前的位置,然后遍历所有位置以创建注释。这会导致相同的注释被多次添加到地图中。您可以将 iterateLocations
方法更改为 add(newLocation:[String:Any])
之类的方法,并只传递从用户输入中获得的最后一个位置。
所以一种解决方案是替换:
let mapVC : MapViewController = MapViewController()
里面 addToMap
有:
let mapVC : MapViewController = self.tabBarController!.viewControllers![1] as! MapViewController
mapVC.loadViewIfNeeded()
mapVC.add(newLocation:location)
假设 OtherVC
位于标签视图控制器的索引 0,MapViewController
位于索引 1。还有:
func add(newLocation location:[String:Any]) {
let momentaryLat = (location["latitude"] as! NSString).doubleValue
let momentaryLong = (location["longitude"] as! NSString).doubleValue
let annotation = MKPointAnnotation()
annotation.title = location["title"] as? String
annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
mapView.addAnnotation(annotation)
}