在MapView中search注释
我遵循了一个关于在mapView
searchannotations
以及在MKLocalSearch
search世界的方法的如何search位置使用苹果 MKLocalSearch
。
但是,我不想用MKLocalSearch
进行search,而是search我自己的annotations
,例如我自己添加了这些annotations
:
let LitzmanLocation = CLLocationCoordinate2DMake(32.100668,34.775192) // Drop a pin let Litzman = MKPointAnnotation() Litzman.coordinate = LitzmanLocation Litzman.title = "Litzman Bar" Litzman.subtitle = "נמל תל אביב 18,תל אביב" mapView.addAnnotation(Litzman) let ShalvataLocation = CLLocationCoordinate2DMake(32.101145,34.775163) // Drop a pin let Shalvata = MKPointAnnotation() Shalvata.coordinate = ShalvataLocation Shalvata.title = "Shalvata" Shalvata.subtitle = "האנגר 28,נמל תל אביב" mapView.addAnnotation(Shalvata) let MarkidLocation = CLLocationCoordinate2DMake(32.074961,34.781679) // Drop a pin let Markid = MKPointAnnotation() Markid.coordinate = MarkidLocation Markid.title = "Markid" Markid.subtitle = "אבן גבירול 30,תל אביב" mapView.addAnnotation(Markid)
这是我的代码:
MapViewController.Swift:
import UIKit import MapKit import CoreLocation protocol HandleMapSearch { func dropPinZoomIn(placemark:MKPlacemark) } class MapViewController: UIViewController,MKMapViewDelegate, CLLocationManagerDelegate,UISearchBarDelegate{ @IBOutlet var mapView: MKMapView! var resultSearchController:UISearchController? = nil var selectedPin:MKPlacemark? = nil @IBAction func MapSearchController(sender: AnyObject) { resultSearchController!.hidesNavigationBarDuringPresentation = false self.resultSearchController!.searchBar.delegate = self presentViewController(resultSearchController!, animated: true, completion: nil) self.resultSearchController!.searchBar.barTintColor = UIColor.blackColor() self.resultSearchController!.searchBar.placeholder = "חפש ברים" self.resultSearchController!.dimsBackgroundDuringPresentation = true self.resultSearchController!.searchBar.sizeToFit() } override func viewDidLoad() { super.viewDidLoad() let locationSearchTable = storyboard!.instantiateViewControllerWithIdentifier("LocationSearchTable") as! LocationSearchTable resultSearchController = UISearchController(searchResultsController: locationSearchTable) resultSearchController?.searchResultsUpdater = locationSearchTable locationSearchTable.mapView = mapView locationSearchTable.handleMapSearchDelegate = self } } } extension MapViewController: HandleMapSearch { func dropPinZoomIn(placemark:MKPlacemark){ // cache the pin selectedPin = placemark // clear existing pins mapView.removeAnnotations(mapView.annotations) let annotation = MKPointAnnotation() annotation.coordinate = placemark.coordinate annotation.title = placemark.name if let city = placemark.locality, let state = placemark.administrativeArea { annotation.subtitle = "(city) (state)" } mapView.addAnnotation(annotation) let span = MKCoordinateSpanMake(0.05, 0.05) let region = MKCoordinateRegionMake(placemark.coordinate, span) mapView.setRegion(region, animated: true) } }
LocalSearchTable.Swift:
import UIKit import MapKit class LocationSearchTable : UITableViewController { var matchingItems:[MKMapItem] = [] var mapView: MKMapView? = nil var handleMapSearchDelegate:HandleMapSearch? = nil func parseAddress(selectedItem:MKPlacemark) -> String { // put a space between "4" and "Melrose Place" let firstSpace = (selectedItem.subThoroughfare != nil && selectedItem.thoroughfare != nil) ? " " : "" // put a comma between street and city/state let comma = (selectedItem.subThoroughfare != nil || selectedItem.thoroughfare != nil) && (selectedItem.subAdministrativeArea != nil || selectedItem.administrativeArea != nil) ? ", " : "" // put a space between "Washington" and "DC" let secondSpace = (selectedItem.subAdministrativeArea != nil && selectedItem.administrativeArea != nil) ? " " : "" let addressLine = String( format:"%@%@%@%@%@%@%@", // street number selectedItem.subThoroughfare ?? "", firstSpace, // street name selectedItem.thoroughfare ?? "", comma, // city selectedItem.locality ?? "", secondSpace, // state selectedItem.administrativeArea ?? "" ) return addressLine } } extension LocationSearchTable : UISearchResultsUpdating { func updateSearchResultsForSearchController(searchController: UISearchController) { guard let mapView = mapView, let searchBarText = searchController.searchBar.text else { return } let request = MKLocalSearchRequest() request.naturalLanguageQuery = searchBarText request.region = mapView.region let search = MKLocalSearch(request: request) search.startWithCompletionHandler { response, _ in guard let response = response else { return } self.matchingItems = response.mapItems self.tableView.reloadData() } } } extension LocationSearchTable { override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return matchingItems.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("MapSearchCell")! let selectedItem = matchingItems[indexPath.row].placemark cell.textLabel?.text = selectedItem.name cell.detailTextLabel?.text = parseAddress(selectedItem) return cell } } extension LocationSearchTable { override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let selectedItem = matchingItems[indexPath.row].placemark handleMapSearchDelegate?.dropPinZoomIn(selectedItem) dismissViewControllerAnimated(true, completion: nil) } }
您将了解以下主题
- 在地图中显示注释。
- 在地图中显示自定义注释。
- 在地图中使用自定义button显示自定义注释。
TL; DR
示例项目: https : //github.com/JakubMazur/SO40539590
好的,一开始我会build议你从你的控制器代码中分离数据。 我selectjson
格式作为最普遍的一个。 所以:
[ { "title":"Litzman Bar", "subtitle":"נמל תל אביב 18,תל אביב", "coordinates":{ "lat":32.100668, "lon":34.775192 } }, { "title":"Shalvata", "subtitle":"האנגר 28,נמל תל אביב", "coordinates":{ "lat":32.101145, "lon":34.775163 } }, { "title":"Markid", "subtitle":"אבן גבירול 30,תל אביב", "coordinates":{ "lat":32.074961, "lon":34.781679 } } ]
这基本上是你的数据库。
现在让我们把它parsing成你的ViewConttroller
使用的Array
。 再次,我会build议你将其分割成模型对象,如Location
和Coordinate
。 我们来看看它的一个类作为例子:
class Location: NSObject { var title : String = String() var subtitle : String = String() var coordinates : Coordinate = Coordinate() public class func locationFromDictionary(_ dictionary : Dictionary<String, AnyObject>) -> Location { let location : Location = Location() location.title = dictionary["title"] as! String location.subtitle = dictionary["subtitle"] as! String location.coordinates = Coordinate.coordinateFromDictionary(dictionary["coordinates"] as! Dictionary<String, AnyObject>) return location; } }
我不会将用于parsingjson
文件的代码粘贴到这个对象上,因为这个问题不是这个问题。 你会发现到存储库。
现在让我们把重点放在问题上。
我会build议你不要search注释,而是search你的数据模型,并在需要时重新绘制注释
为了做到这一点(我将使用UISearchBar
):
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { self.displayArray = self.locationsDatabase.filter() { return $0.title.contains("i") }
那么当你像这样一个二传手:
var displayArray : Array<Location> = [] { didSet { self.mapView .removeAnnotations(self.mapView.annotations) for location in displayArray { let coords : Coordinate = location.coordinates let point = MKPointAnnotation() point.coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(coords.latitude),CLLocationDegrees(coords.longitude)) point.title = location.title point.subtitle = location.subtitle mapView.addAnnotation(point) } } }
您可以重绘您的注释。 像空search领域,案件敏感性,解雇键盘的边缘情况下,我给你。 但希望你能得到一般的想法。 你可能会认为它是过度工程,但将对象作为一个单独的类和通用格式作为数据input可能在未来受益。
完整的项目: https : //github.com/JakubMazur/SO40539590