Swift 点击tableview的单元格时,将用户指向注释

Swift 点击tableview的单元格时,将用户指向注释,swift,annotations,tableview,mapkit,Swift,Annotations,Tableview,Mapkit,简而言之,用户点击tableview中的一行(其中包含来自某个位置的数据),我希望在用户点击该行时显示带有适当注释的地图。到目前为止没有运气。 我已经实现了使用委托模式的建议。现在我已经实现了它,应用程序不断崩溃 我将发布代码,但在浏览了几十个堆栈溢出问题后,我无法解决它。希望你们能帮忙 //主控制器 import UIKit import MapKit import CoreLocation class ViewController: UIViewController, CLLocation

简而言之,用户点击tableview中的一行(其中包含来自某个位置的数据),我希望在用户点击该行时显示带有适当注释的地图。到目前为止没有运气。

我已经实现了使用委托模式的建议。现在我已经实现了它,应用程序不断崩溃

我将发布代码,但在浏览了几十个堆栈溢出问题后,我无法解决它。希望你们能帮忙

//主控制器

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate {

override func viewDidLoad() {
        super.viewDidLoad()
   }
//SearchTable initiation
    let searchTable = storyboard!.instantiateViewController(withIdentifier: "SearchTableViewController") as! SearchTableViewController

    searchController = UISearchController(searchResultsController: searchTable)
    searchController?.searchResultsUpdater = searchTable
    searchController?.hidesNavigationBarDuringPresentation = false
    searchController?.dimsBackgroundDuringPresentation = true

    searchController?.definesPresentationContext = true

    //Searchbar initiation
    let searchBar = searchController!.searchBar
    searchBar.sizeToFit()
    searchBar.keyboardAppearance = UIKeyboardAppearance.dark
    searchBar.placeholder = "Search locations"
    navigationItem.titleView = searchController?.searchBar
    searchBar.delegate = self

    searchTable.mapView = mapView
    searchTable.handleMapSearchDelegate = self
}


//Update the map
func updateMap(_ location: CLLocation)  {
    let region = MKCoordinateRegion.init(center: location.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
    mapView.setRegion(region, animated: true)
}

//Cancel searchBar
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.text = nil
        searchBar.setShowsCancelButton(false, animated: true)
        searchBar.endEditing(true)
    }
}

//Center the map on current user's location
extension ViewController: MKMapViewDelegate {
    func centerMapOnUserLocation() {
        guard let coordinate = locationManager.location?.coordinate else { return }
        let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: regionRadius * 2.0, longitudinalMeters: regionRadius * 2.0)
        mapView.setRegion(coordinateRegion, animated: true)
    }
}

//Zoom into selected location from search
extension ViewController: HandleMapSearch   {
    func dropPinZoomIn(placemark: MKAnnotation)    {
        updateMap(CLLocation(latitude: placemark.coordinate.latitude, longitude: placemark.coordinate.longitude))
        searchController.searchBar.text = placemark.title!
    }
}

//Zoom into selected location from selectedRow
extension ViewController: HandleSelectedLocation   {
    func dropPinAndZoomIn(placemark: MKAnnotation)    {
        updateMap(CLLocation(latitude: placemark.coordinate.latitude, longitude: placemark.coordinate.longitude))
    }
}
import UIKit
import MapKit

protocol HandleSelectedLocation {
    func dropPinAndZoomIn(placemark: MKAnnotation)
}


//Initialize the TableViewController
class CategoriesController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    //Variables
    var mapView: MKMapView?
    var selectedItem = [MKAnnotation]()

    var handleSelectedLocationDelegate: HandleSelectedLocation? = nil

    //Outlet
    @IBOutlet var tableView: UITableView!

    //Load view
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = self
        tableView.delegate = self
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return location.count

    }

    //Fill cells with locations
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "allCell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "allCell")

        let locations = location[indexPath.row]
        cell.textLabel?.text = locations.title
        cell.textLabel?.textColor = UIColor.white
        cell.detailTextLabel?.text = locations.rating
        cell.detailTextLabel?.textColor = UIColor.white

        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let annotation = mapView!.annotations
        let locationSelected = annotation[indexPath.row]
        handleSelectedLocationDelegate?.dropPinAndZoomIn(placemark: locationSelected)
        tableView.isHidden = true
    }
}
**protocol HandleMapSearch    {
    func dropPinZoomIn(placemark: MKAnnotation)
}

//Make searches appear

class SearchTableViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    //Variables
    var mapView: MKMapView? = nil
    var matchingItems = [MKAnnotation]()
    var handleMapSearchDelegate: HandleMapSearch? = nil

    func updateSearchResults(for searchController: UISearchController) {
        guard let _ = mapView,
            let searchBarText = searchController.searchBar.text else { return  }

        matchingItems = self.mapView!.annotations.filter { annotation -> Bool in
            if annotation.title!?.range(of: searchBarText, options: .caseInsensitive) != nil {
                return true
            }

            if annotation.subtitle!?.range(of: searchBarText, options: .caseInsensitive) != nil {
                return true
            }

            return false
        }

        self.tableView.reloadData()
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return matchingItems.count
    }

    //Fill tableView with location provided by search
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "cell")

        let selectedItem = matchingItems[indexPath.row]
        cell.textLabel?.text = selectedItem.title!
        cell.textLabel?.textColor = UIColor.white
        cell.detailTextLabel?.text = selectedItem.subtitle!
        cell.detailTextLabel?.textColor = UIColor.white

        return cell
    }

    //Go to map and show selected annotation
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selectedItem = matchingItems[indexPath.row]
        handleMapSearchDelegate?.dropPinZoomIn(placemark: selectedItem)
        dismiss(animated: true, completion: nil)
    }
}**
//TABLEVIEWCONTROLLER

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate {

override func viewDidLoad() {
        super.viewDidLoad()
   }
//SearchTable initiation
    let searchTable = storyboard!.instantiateViewController(withIdentifier: "SearchTableViewController") as! SearchTableViewController

    searchController = UISearchController(searchResultsController: searchTable)
    searchController?.searchResultsUpdater = searchTable
    searchController?.hidesNavigationBarDuringPresentation = false
    searchController?.dimsBackgroundDuringPresentation = true

    searchController?.definesPresentationContext = true

    //Searchbar initiation
    let searchBar = searchController!.searchBar
    searchBar.sizeToFit()
    searchBar.keyboardAppearance = UIKeyboardAppearance.dark
    searchBar.placeholder = "Search locations"
    navigationItem.titleView = searchController?.searchBar
    searchBar.delegate = self

    searchTable.mapView = mapView
    searchTable.handleMapSearchDelegate = self
}


//Update the map
func updateMap(_ location: CLLocation)  {
    let region = MKCoordinateRegion.init(center: location.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
    mapView.setRegion(region, animated: true)
}

//Cancel searchBar
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.text = nil
        searchBar.setShowsCancelButton(false, animated: true)
        searchBar.endEditing(true)
    }
}

//Center the map on current user's location
extension ViewController: MKMapViewDelegate {
    func centerMapOnUserLocation() {
        guard let coordinate = locationManager.location?.coordinate else { return }
        let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: regionRadius * 2.0, longitudinalMeters: regionRadius * 2.0)
        mapView.setRegion(coordinateRegion, animated: true)
    }
}

//Zoom into selected location from search
extension ViewController: HandleMapSearch   {
    func dropPinZoomIn(placemark: MKAnnotation)    {
        updateMap(CLLocation(latitude: placemark.coordinate.latitude, longitude: placemark.coordinate.longitude))
        searchController.searchBar.text = placemark.title!
    }
}

//Zoom into selected location from selectedRow
extension ViewController: HandleSelectedLocation   {
    func dropPinAndZoomIn(placemark: MKAnnotation)    {
        updateMap(CLLocation(latitude: placemark.coordinate.latitude, longitude: placemark.coordinate.longitude))
    }
}
import UIKit
import MapKit

protocol HandleSelectedLocation {
    func dropPinAndZoomIn(placemark: MKAnnotation)
}


//Initialize the TableViewController
class CategoriesController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    //Variables
    var mapView: MKMapView?
    var selectedItem = [MKAnnotation]()

    var handleSelectedLocationDelegate: HandleSelectedLocation? = nil

    //Outlet
    @IBOutlet var tableView: UITableView!

    //Load view
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = self
        tableView.delegate = self
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return location.count

    }

    //Fill cells with locations
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "allCell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "allCell")

        let locations = location[indexPath.row]
        cell.textLabel?.text = locations.title
        cell.textLabel?.textColor = UIColor.white
        cell.detailTextLabel?.text = locations.rating
        cell.detailTextLabel?.textColor = UIColor.white

        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let annotation = mapView!.annotations
        let locationSelected = annotation[indexPath.row]
        handleSelectedLocationDelegate?.dropPinAndZoomIn(placemark: locationSelected)
        tableView.isHidden = true
    }
}
**protocol HandleMapSearch    {
    func dropPinZoomIn(placemark: MKAnnotation)
}

//Make searches appear

class SearchTableViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    //Variables
    var mapView: MKMapView? = nil
    var matchingItems = [MKAnnotation]()
    var handleMapSearchDelegate: HandleMapSearch? = nil

    func updateSearchResults(for searchController: UISearchController) {
        guard let _ = mapView,
            let searchBarText = searchController.searchBar.text else { return  }

        matchingItems = self.mapView!.annotations.filter { annotation -> Bool in
            if annotation.title!?.range(of: searchBarText, options: .caseInsensitive) != nil {
                return true
            }

            if annotation.subtitle!?.range(of: searchBarText, options: .caseInsensitive) != nil {
                return true
            }

            return false
        }

        self.tableView.reloadData()
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return matchingItems.count
    }

    //Fill tableView with location provided by search
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "cell")

        let selectedItem = matchingItems[indexPath.row]
        cell.textLabel?.text = selectedItem.title!
        cell.textLabel?.textColor = UIColor.white
        cell.detailTextLabel?.text = selectedItem.subtitle!
        cell.detailTextLabel?.textColor = UIColor.white

        return cell
    }

    //Go to map and show selected annotation
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selectedItem = matchingItems[indexPath.row]
        handleMapSearchDelegate?.dropPinZoomIn(placemark: selectedItem)
        dismiss(animated: true, completion: nil)
    }
}**
//SEARCHTABLEVIEWCONTROLLER

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate {

override func viewDidLoad() {
        super.viewDidLoad()
   }
//SearchTable initiation
    let searchTable = storyboard!.instantiateViewController(withIdentifier: "SearchTableViewController") as! SearchTableViewController

    searchController = UISearchController(searchResultsController: searchTable)
    searchController?.searchResultsUpdater = searchTable
    searchController?.hidesNavigationBarDuringPresentation = false
    searchController?.dimsBackgroundDuringPresentation = true

    searchController?.definesPresentationContext = true

    //Searchbar initiation
    let searchBar = searchController!.searchBar
    searchBar.sizeToFit()
    searchBar.keyboardAppearance = UIKeyboardAppearance.dark
    searchBar.placeholder = "Search locations"
    navigationItem.titleView = searchController?.searchBar
    searchBar.delegate = self

    searchTable.mapView = mapView
    searchTable.handleMapSearchDelegate = self
}


//Update the map
func updateMap(_ location: CLLocation)  {
    let region = MKCoordinateRegion.init(center: location.coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
    mapView.setRegion(region, animated: true)
}

//Cancel searchBar
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.text = nil
        searchBar.setShowsCancelButton(false, animated: true)
        searchBar.endEditing(true)
    }
}

//Center the map on current user's location
extension ViewController: MKMapViewDelegate {
    func centerMapOnUserLocation() {
        guard let coordinate = locationManager.location?.coordinate else { return }
        let coordinateRegion = MKCoordinateRegion(center: coordinate, latitudinalMeters: regionRadius * 2.0, longitudinalMeters: regionRadius * 2.0)
        mapView.setRegion(coordinateRegion, animated: true)
    }
}

//Zoom into selected location from search
extension ViewController: HandleMapSearch   {
    func dropPinZoomIn(placemark: MKAnnotation)    {
        updateMap(CLLocation(latitude: placemark.coordinate.latitude, longitude: placemark.coordinate.longitude))
        searchController.searchBar.text = placemark.title!
    }
}

//Zoom into selected location from selectedRow
extension ViewController: HandleSelectedLocation   {
    func dropPinAndZoomIn(placemark: MKAnnotation)    {
        updateMap(CLLocation(latitude: placemark.coordinate.latitude, longitude: placemark.coordinate.longitude))
    }
}
import UIKit
import MapKit

protocol HandleSelectedLocation {
    func dropPinAndZoomIn(placemark: MKAnnotation)
}


//Initialize the TableViewController
class CategoriesController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    //Variables
    var mapView: MKMapView?
    var selectedItem = [MKAnnotation]()

    var handleSelectedLocationDelegate: HandleSelectedLocation? = nil

    //Outlet
    @IBOutlet var tableView: UITableView!

    //Load view
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.dataSource = self
        tableView.delegate = self
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return location.count

    }

    //Fill cells with locations
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "allCell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "allCell")

        let locations = location[indexPath.row]
        cell.textLabel?.text = locations.title
        cell.textLabel?.textColor = UIColor.white
        cell.detailTextLabel?.text = locations.rating
        cell.detailTextLabel?.textColor = UIColor.white

        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let annotation = mapView!.annotations
        let locationSelected = annotation[indexPath.row]
        handleSelectedLocationDelegate?.dropPinAndZoomIn(placemark: locationSelected)
        tableView.isHidden = true
    }
}
**protocol HandleMapSearch    {
    func dropPinZoomIn(placemark: MKAnnotation)
}

//Make searches appear

class SearchTableViewController: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {

    //Variables
    var mapView: MKMapView? = nil
    var matchingItems = [MKAnnotation]()
    var handleMapSearchDelegate: HandleMapSearch? = nil

    func updateSearchResults(for searchController: UISearchController) {
        guard let _ = mapView,
            let searchBarText = searchController.searchBar.text else { return  }

        matchingItems = self.mapView!.annotations.filter { annotation -> Bool in
            if annotation.title!?.range(of: searchBarText, options: .caseInsensitive) != nil {
                return true
            }

            if annotation.subtitle!?.range(of: searchBarText, options: .caseInsensitive) != nil {
                return true
            }

            return false
        }

        self.tableView.reloadData()
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return matchingItems.count
    }

    //Fill tableView with location provided by search
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell(style: .subtitle, reuseIdentifier: "cell")

        let selectedItem = matchingItems[indexPath.row]
        cell.textLabel?.text = selectedItem.title!
        cell.textLabel?.textColor = UIColor.white
        cell.detailTextLabel?.text = selectedItem.subtitle!
        cell.detailTextLabel?.textColor = UIColor.white

        return cell
    }

    //Go to map and show selected annotation
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selectedItem = matchingItems[indexPath.row]
        handleMapSearchDelegate?.dropPinZoomIn(placemark: selectedItem)
        dismiss(animated: true, completion: nil)
    }
}**
//CustomAnnotation

import Foundation
import MapKit

class CustomAnnotation: NSObject, MKAnnotation {
    var coordinate: CLLocationCoordinate2D
    var extraDescription: String?
    var title: String?
    var subtitle: String?
    var country: String?

    init(coordinate: CLLocationCoordinate2D) {
        self.coordinate = coordinate
    }
}
//位置结构

import Foundation
import UIKit
import MapKit

//Annotations
struct SomeLocation {
    let title: String
    let rating: String
    let description: String
    let country: String
    let latitude: Double
    let longitude: Double
}
问题:我是否正确实现了委托模式? 当我添加最后一个扩展时,它给了我启动应用程序的问题。在扭转了这个变化之后,它起了作用,但当然,该代表什么也没做

如果您需要任何澄清或额外代码,请询问


我似乎无法解决这个问题,非常感谢大家的帮助

代理模式如何

e、 g

主视图控制器:

...
let vc = SecondViewController
vc.delegate = self
...

extension MainViewController: SecondViewControllerDelegate {
    func didSelectRow(at: YourLocationType) {
        // Direct user to annotation when cell of tableview tapped
    }
}

委托模式如何

e、 g

主视图控制器:

...
let vc = SecondViewController
vc.delegate = self
...

extension MainViewController: SecondViewControllerDelegate {
    func didSelectRow(at: YourLocationType) {
        // Direct user to annotation when cell of tableview tapped
    }
}

尝试委托模式。在tableview上,点击调用主视图控制器的方法,将引用传递给所需的location@pckill的模式是实现这种实现的好方法。如果您在实现它时遇到困难,请与我们分享您的代码,我们可以提供帮助。@pckill您能看看我更新的代码吗?我曾尝试实现委托模式,但应用程序不断崩溃。“我很抱歉反应太晚,但我有一些紧急的个人情况需要处理。”JamieCoenen,阅读。请在寻求帮助时提供帮助。例如,这个
searchController
是什么?您在哪里初始化它?@pckill我已经添加了
searchBar
/
searchController
(它来自UISearchBar类型)中的代码以及其他一些片段,以明确它是如何工作的。对于意外发现的nil,只有在添加扩展名
HandleSelectedLocation
时才会发生这种情况,否则这一行执行时不会出现问题。请尝试委托模式。在tableview上,点击调用主视图控制器的方法,将引用传递给所需的location@pckill的模式是实现这种实现的好方法。如果您在实现它时遇到困难,请与我们分享您的代码,我们可以提供帮助。@pckill您能看看我更新的代码吗?我曾尝试实现委托模式,但应用程序不断崩溃。“我很抱歉反应太晚,但我有一些紧急的个人情况需要处理。”JamieCoenen,阅读。请在寻求帮助时提供帮助。例如,这个
searchController
是什么?您在哪里初始化它?@pckill我已经添加了
searchBar
/
searchController
(它来自UISearchBar类型)中的代码以及其他一些片段,以明确它是如何工作的。对于意外发现的nil,只有在我添加扩展名
HandleSelectedLocation
时才会发生这种情况,否则这行执行时不会出现问题。感谢您的回答!你能看一下更新的代码吗?我已经实现了委托模式,但不知何故它似乎不起作用。谢谢你的回答!你能看一下更新的代码吗?我已经实现了委托模式,但不知何故它似乎不起作用。