簡體   English   中英

UI Tableview 不會在單元格中顯示或更新搜索結果,Swift

[英]UI Tableview won't display or update search results in cells, Swift

我是一名中級 Swift 開發人員,我正在創建一個應用程序,該應用程序涉及使用搜索 function 來查找地址並在 map 上查明所述地址。 我遵循了一個關於如何實現這一點的教程,除了搜索 function 本身之外,一切都正常。 每當我在 UIsearchbar 中鍵入時,我的搜索結果 tableview controller 都會被實例化,但是,table view 是空白的,並且在我鍵入時不會更新。 應該存在地址 API 調用。

下面是我的搜索表代碼

import UIKit
import MapKit


class LocationSearchTable : UITableViewController {
    
    var resultSearchController:UISearchController? = nil
    var handleMapSearchDelegate:HandleMapSearch? = nil
    var matchingItems:[MKMapItem] = []
    var mapView: MKMapView? = nil
    @IBOutlet var searchTableView: UITableView!
    
}
extension LocationSearchTable : UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        searchController.showsSearchResultsController = true
    }
    
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        guard let mapView = mapView,
              let searchBarText = searchController.searchBar.text else { return }
        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = searchBarText
        request.region = mapView.region
        let search = MKLocalSearch(request: request)
        search.start { 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
        
    }
    func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
        let selectedItem = matchingItems[indexPath.row].placemark
        cell.textLabel?.text = selectedItem.name
        cell.detailTextLabel?.text = ""
        return cell
    }
}
extension LocationSearchTable {
        func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let selectedItem = matchingItems[indexPath.row].placemark
            handleMapSearchDelegate?.dropPinZoomIn(placemark: selectedItem)
            dismiss(animated: true, completion: nil)
    }
}

這是我的初始視圖 controller 的代碼

import UIKit
import MapKit
import CoreLocation

protocol HandleMapSearch {
    func dropPinZoomIn(placemark:MKPlacemark)
}
//for some reason my location delegate is not working (resolved)
class locationViewController: UIViewController, UISearchResultsUpdating, UISearchBarDelegate {
    
    func updateSearchResults(for searchController: UISearchController) {
        return
        
        
    }
    
   
    
    var selectedPin:MKPlacemark? = nil
    
    var resultSearchController:UISearchController? = nil
    @IBOutlet weak var eventLocationMapView: MKMapView!
    @IBOutlet weak var backButton: UIButton!
    
    let locationManager = CLLocationManager()
    let regionInMeters: Double = 10000
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
       
        resultSearchController?.searchResultsUpdater = self
        
        let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTable
        resultSearchController = UISearchController(searchResultsController: locationSearchTable)
        resultSearchController?.searchResultsUpdater = locationSearchTable
        resultSearchController?.searchBar.delegate = self
       
            locationSearchTable.mapView = eventLocationMapView
       
        let searchBar = resultSearchController!.searchBar
                
        searchBar.sizeToFit()
                
        searchBar.placeholder = "Search for places"
        //this is the search bar
        navigationItem.titleView = resultSearchController?.searchBar
                
        resultSearchController?.hidesNavigationBarDuringPresentation = false
                
        resultSearchController?.obscuresBackgroundDuringPresentation = true
                
        definesPresentationContext = true
        
        locationSearchTable.handleMapSearchDelegate = self
        //all of this is in regards to the search functionality
        
        locationManager.startUpdatingLocation()
        self.checkLocationAuthorization()
        self.checkLocationServices()
        self.navigationController?.isNavigationBarHidden = false
        // Do any additional setup after loading the view.
        locationManager.requestWhenInUseAuthorization()
        //this pushes the user request. The issue was most likely in the switch statement
        locationManager.delegate = self
        locationManager.requestLocation()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest

        //solved it but we will probably have to go back to this
        
        self.centerViewOnUserLocation()
    }
        
    @IBAction func backButtonTapped(_ sender: Any) {
        
        self.transitionBackToCreateEventVC()
        
    }
        

    func transitionBackToCreateEventVC (){
        let createEventViewController = self.storyboard?.instantiateViewController(identifier: "createEventVC")
        
        self.view.window?.rootViewController = createEventViewController
        self.view.window?.makeKeyAndVisible()
        
        
        
    }
    func centerViewOnUserLocation() {
        
        if let location = locationManager.location?.coordinate {
            let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
            eventLocationMapView.setRegion(region, animated: true)
            //this function centers the map onto the location of the user
        }
        
    }
    
    
    func setUpLocationManager(){
        
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        
    }
    func checkLocationServices(){
        
        if CLLocationManager.locationServicesEnabled(){
            setUpLocationManager()
            checkLocationAuthorization()
        } else {
            //show alert letting the user know they have to turn this on
        }
        
    }
    func checkLocationAuthorization() {
        
        let locationManager = CLLocationManager()
        switch locationManager.authorizationStatus {
        case .authorizedWhenInUse:
            
            eventLocationMapView.showsUserLocation = true
            // We want the users location while the app is in use
            break
        case .denied:
            //show alert instructing how to turn on permissions
            break
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
            return
        case .restricted:
            //show an alert
            break
        case .authorizedAlways:
            // we don't want this
            break
        @unknown default:
            return
            //I dont know if we need this code
        }
        
    }
    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}
extension locationViewController: CLLocationManagerDelegate {
    
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse {
              locationManager.requestLocation()
          }
      }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
       
        if let location = locations.first {
            
            let region = MKCoordinateRegion(center: location.coordinate, latitudinalMeters: 0.05 , longitudinalMeters: 0.05)
                    eventLocationMapView.setRegion(region, animated: true)
            
        }
        
    }
    public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
            print("error:: \(error)")
    }
}
extension locationViewController: HandleMapSearch {
    func dropPinZoomIn(placemark:MKPlacemark){
        // cache the pin
        selectedPin = placemark
        // clear existing pins
        eventLocationMapView.removeAnnotations(eventLocationMapView.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)"
        }
        eventLocationMapView.addAnnotation(annotation)
        let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
        let region = MKCoordinateRegion(center: placemark.coordinate, span: span)
        eventLocationMapView.setRegion(region, animated: true)
    }
}


我認為您應該在LocationSearchTable class 中創建一個屬性來保存MKLocalSearch object。

class LocationSearchTable : UITableViewController {
    private var search: MKLocalSearch?
    // ...
}

extension LocationSearchTable : UISearchResultsUpdating {
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        guard let mapView = mapView,
              let searchBarText = searchController.searchBar.text else { return }
        // if there is an ongoing search, cancel it first.
        self.search?.cancel()

        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = searchBarText
        request.region = mapView.region
        let search = MKLocalSearch(request: request)
        search.start { response, error in
            guard let response = response
            else {
                return
            }
            self.matchingItems = response.mapItems
            self.tableView.reloadData()
        }
        // make sure `search` is not released.
        self.search = search
    }

}

原代碼的問題是, search object,MKLocalSearch 實例MKLocalSearch將在執行完updateSearchResultsForSearchController方法后被釋放,因為沒有強引用它,並且start的回調永遠不會被調用,所以你的表視圖將永遠不會重新加載。

我們所做的只是對其進行強引用,並確保在調用完成處理程序之前它不會被釋放。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM