首页 > 解决方案 > 带有子视图的 MapKit 地图不会添加注释

问题描述

我目前正在尝试实现与搜索功能连接的地图。对于包含表格视图的覆盖,我决定使用一个名为FloatingPanel的库。无论如何,这不应该是重要的,因为它不应该影响基本代码等。

数据正在内部读取并由SearchResultsTableViewController传递给。 在调用from的函数内部被调用来处理数据 - 在函数内部打印将始终返回正确的值。MapViewControllerpassData()
passData()addAnnotationToMap()MapViewController

在函数内部,我试图向地图添加注释,但它不起作用。什么都没有发生-但是当我这样做时print(mapView.annotations),将返回包括我的注释数组。

顺便说一句,我不得不添加loadViewIfNeeded()MapViewController因为没有(在使用覆盖视图之后)mapView返回 nil。

抱歉代码量大 - 但可能有一些相关代码。我没有包含表格视图的代码。

地图视图控制器

class MapViewController: UIViewController, FloatingPanelControllerDelegate, UISearchBarDelegate {

    var fpc: FloatingPanelController!
    var searchVC = SearchResultTableViewController()

    private enum AnnotationReuseID: String {
        case pin
    }

    @IBOutlet private var mapView: MKMapView!

    var mapItems: [MKMapItem]?
    var boundingRegion: MKCoordinateRegion?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let region = boundingRegion {
            mapView.region = region
        }


        fpc = FloatingPanelController()
        fpc.delegate = self

        // Initialize FloatingPanelController and add the view
        fpc.surfaceView.backgroundColor = .clear
        fpc.surfaceView.cornerRadius = 9.0
        fpc.surfaceView.shadowHidden = false

        searchVC = (storyboard?.instantiateViewController(withIdentifier: "SearchPanel") as! SearchResultTableViewController)

        // Set a content view controller
        fpc.set(contentViewController: searchVC)
        fpc.track(scrollView: searchVC.tableView)

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        //  Add FloatingPanel to a view with animation.
        fpc.addPanel(toParent: self, animated: true)
        fpc.move(to: .tip, animated: true)

        // Must be here
        searchVC.searchController.searchBar.delegate = self

    }

    func addAnnotationToMap() {
        loadViewIfNeeded()
        guard let item = mapItems?.first else { return }

        guard let coordinate = item.placemark.location?.coordinate else { return }
        let annotation = MKPointAnnotation()
        annotation.title = item.name
        annotation.coordinate = coordinate
        mapView.addAnnotation(annotation)
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.resignFirstResponder()
        searchBar.showsCancelButton  = false
        fpc.move(to: .tip, animated: true)
    }

    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
        searchBar.showsCancelButton = true
        searchVC.tableView.alpha = 1.0
        fpc.move(to: .full, animated: true)
        searchVC.hideHeader()
    }

    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        fpc.move(to: .half, animated: true)
        searchVC.showHeader()
    }

    func floatingPanelDidMove(_ vc: FloatingPanelController) {
        let y = vc.surfaceView.frame.origin.y
        let tipY = vc.originYOfSurface(for: .tip)
        if y > tipY - 44.0 {
            let progress = max(0.0, min((tipY  - y) / 44.0, 1.0))
            self.searchVC.tableView.alpha = progress
        }
    }

    func floatingPanelWillBeginDragging(_ vc: FloatingPanelController) {
        if vc.position == .full {
            searchVC.searchBar.showsCancelButton = false
            searchVC.searchBar.resignFirstResponder()
        }
    }

    func floatingPanelDidEndDragging(_ vc: FloatingPanelController, withVelocity velocity: CGPoint, targetPosition: FloatingPanelPosition) {

        UIView.animate(withDuration: 0.25,
                       delay: 0.0,
                       options: .allowUserInteraction,
                       animations: {
                        if targetPosition == .tip {
                            self.searchVC.tableView.alpha = 0.0
                            self.searchVC.hideHeader()
                        } else if targetPosition == .half {
                            self.searchVC.tableView.alpha = 1.0
                            self.searchVC.showHeader()
                        } else {
                            self.searchVC.tableView.alpha = 1.0
                            self.searchVC.hideHeader()
                        }
        }, completion: nil)
    }
}

搜索视图控制器

class SearchResultTableViewController: UIViewController {

    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var visualEffectView: UIVisualEffectView!

    private enum CellReuseID: String {
        case resultCell
    }

    private var places: [MKMapItem]? {
        didSet {
            tableView.reloadData()
        }
    }

    private var suggestionController: SuggestionsTableTableViewController!
    var searchController: UISearchController!


    private var localSearch: MKLocalSearch? {
        willSet {
            places = nil
            localSearch?.cancel()
        }
    }

    private var boundingRegion: MKCoordinateRegion?

    override func awakeFromNib() {
        super.awakeFromNib()

        suggestionController = SuggestionsTableTableViewController()
        suggestionController.tableView.delegate = self

        searchController = UISearchController(searchResultsController: suggestionController)
        searchController.searchResultsUpdater = suggestionController

        searchController.searchBar.isUserInteractionEnabled = false
        searchController.searchBar.alpha = 0.5
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        searchBar.addSubview(searchController.searchBar)

        searchController.searchBar.searchBarStyle = .minimal
        searchController.searchBar.tintColor = .black
        searchController.searchBar.isUserInteractionEnabled = true
        searchController.dimsBackgroundDuringPresentation = false

        definesPresentationContext = true

        hideHeader()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        if #available(iOS 10, *) {
            visualEffectView.layer.cornerRadius = 9.0
            visualEffectView.clipsToBounds = true
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

    }

    func showHeader() {
        changeHeader(height: 116.0)
    }

    func hideHeader() {
        changeHeader(height: 0.0)
    }

    func changeHeader(height: CGFloat) {
        tableView.beginUpdates()
        if let headerView = tableView.tableHeaderView  {
            UIView.animate(withDuration: 0.25) {
                var frame = headerView.frame
                frame.size.height = height
                self.tableView.tableHeaderView?.frame = frame
            }
        }
        tableView.endUpdates()
    }

    func passData() {
        guard let mapViewController = storyboard?.instantiateViewController(withIdentifier: "map") as? MapViewController else { return }

        guard let mapItem = places?.first else { return }

        guard let coordinate = mapItem.placemark.location?.coordinate else { return }
        let span = MKCoordinateSpan(latitudeDelta: coordinate.latitude, longitudeDelta: coordinate.longitude)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        mapViewController.boundingRegion = region

        mapViewController.mapItems = [mapItem]
        mapViewController.addAnnotationToMap()

    }



    private func search(for suggestedCompletion: MKLocalSearchCompletion) {
        let searchRequest = MKLocalSearch.Request(completion: suggestedCompletion)
        search(using: searchRequest)
    }

    private func search(for queryString: String?) {
        let searchRequest = MKLocalSearch.Request()
        searchRequest.naturalLanguageQuery = queryString
        search(using: searchRequest)
    }

    private func search(using searchRequest: MKLocalSearch.Request) {

        if let region = boundingRegion {
            searchRequest.region = region
        }

        UIApplication.shared.isNetworkActivityIndicatorVisible = true

        localSearch = MKLocalSearch(request: searchRequest)
        localSearch?.start { [weak self] (response, error) in
            if error == nil {
                self?.passData()
            } else {
                self?.displaySearchError(error)
                return
            }

            self?.places = response?.mapItems

            self?.boundingRegion = response?.boundingRegion

            UIApplication.shared.isNetworkActivityIndicatorVisible = false
        }
    }

    private func displaySearchError(_ error: Error?) {
        if let error = error as NSError?, let errorString = error.userInfo[NSLocalizedDescriptionKey] as? String {
            let alertController = UIAlertController(title: "Could not find any places.", message: errorString, preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            present(alertController, animated: true, completion: nil)
        }
    }
}

标签: iosswift

解决方案


推荐阅读