14.3. Phase 3: Place Search and Navigate

At this point, we will add a Bottom Search Sheet to find the places around and navigate there.

Setting up the Bottom Search Sheet

First, let's add a search button at the bottom of the Map Screen. Open MapView.swift file, and put the following code to add the search button and its constraints:

//
//  MapView.swift
//  App14
//
//  Created by Sakib Miazi on 6/14/23.
//

import UIKit
import MapKit

class MapView: UIView {
    //codes omitted...
    var buttonSearch:UIButton!
    
    override init(frame: CGRect) {
        //codes omitted...
        setupButtonSearch()
        initConstraints()
    }
   //codes omitted...
    
    func setupButtonSearch(){
        buttonSearch = UIButton(type: .system)
        buttonSearch.setTitle(" Search places...  ", for: .normal)
        buttonSearch.titleLabel?.font = UIFont.boldSystemFont(ofSize: 24)
        buttonSearch.setImage(UIImage(systemName: "magnifyingglass.circle.fill"), for: .normal)
        buttonSearch.layer.backgroundColor = UIColor.darkGray.cgColor
        buttonSearch.tintColor = .white
        buttonSearch.layer.cornerRadius = 10
        
        buttonSearch.layer.shadowOffset = .zero
        buttonSearch.layer.shadowRadius = 4
        buttonSearch.layer.shadowOpacity = 0.7
        
        buttonSearch.translatesAutoresizingMaskIntoConstraints = false
        buttonSearch.isHidden = true
        self.addSubview(buttonSearch)
    }
    
    func initConstraints(){
        NSLayoutConstraint.activate([
            //codes omitted...
            buttonSearch.bottomAnchor.constraint(equalTo: buttonCurrentLocation.bottomAnchor),
            buttonSearch.centerXAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerXAnchor),
            buttonSearch.heightAnchor.constraint(equalTo: buttonCurrentLocation.heightAnchor)
        ])
    }
    //codes omitted...
}

Now, let's create the files related to the Bottom Search Sheet in the project: SearchViewController.swift, SearchBottomSheet.swift, SearchTableViewCell.swift, and SearchTableViewManager.swift.

Then we set up the Bottom Search Sheet following the example in .

Bottom Search Sheet

SearchViewController.swift

Let's add the following code to the file:

SearchBottomSheet.swift

Let's add the following code to the file:

SearchTableViewCell.swift

Let's add the following code to the file:

SearchTableViewManager.swift

Let's add the following code to the file:

Displaying the Bottom Search Sheet

We need to add an action to the search button in ViewController. And then display the bottom search sheet.

Let's add the following code in ViewController.swift file:

In the above code:

  • On lines 25 through 38, we handle the action when the user taps on the search button.

    • We create the bottom search sheet and embed it in a navigation controller.

    • Then we define the presentation style, detents, and grabber for the bottom search sheet.

    • Finally, present the sheet.

If we run the app now:

So, our bottom search sheet is working!

Searching Nearby Places

Here we have to type something on the search bar, and depending on what we type, it should display the list of related places in the search results table view. So, let's open SearchViewController.swift and put in the following code to add a delegate to mapview:

In the above code, on line 13, we declare a delegate variable to the ViewController where the map view is.

Now, let's create a new file named LoadPlaces.swift in the group "Map Screen."

Let's write the following code in the file:

In the above code:

  • We import CoreLocation and MapKit libraries to search places.

  • We extend the ViewController class and define the method loadPlacesAround() where we take a String parameter named query.

  • We use MKLocalSearch service from Apple Maps to search for places.

  • On line 16, we create a search request instance.

  • On line 17, we set the naturalLanguageQuery of the local search service to the parameter query.

  • Now, the search request needs a region, right? We won't be searching the whole world. So on line 21, we set the search region to the current map view region. It means I will be looking for places close to the region we see on the map inside the screen.

  • On lines 24 through 38, we run the search for the places related to the query.

Now, let's open SearchViewController.swift file again and call loadPlacesAround() method when the user type something:

In the above code, on line 18, we call the loadPlacesAround(query: searchText) method of map screen using the delegate. We send the text the user writes on the search bar.

We need to update ViewController.swift file to initialize the delegateToMapView variable. So, let's initialize it as the following code:

In the above code, on line 14, we initialize delegateToMapView variable of the search view controller to self.

Let's run the app.

The results are getting printed in the output area in the above demo. The results are related to the search query "coffee." It fetches all the coffee shops around.

Displaying the search results in the search table view

Now we have the search results in the map screen, so we need to send them back to the search result table view. We will use Notification Center for that. We need to observe the data from the search bottom sheet. We post the notification from the map screen.

Setting an observer from the bottom search sheet

Open SearchViewController.swift file, and put the following code there:

In the above code:

  • We observe the notification center on lines 20 through 25.

  • On lines 29 through 32, we define the method for handling the notification received event.

    • We basically receive an array of map items. Then we have to display them in the table view.

Let's open SearchTableViewManager.swift file and add the following code to display the map items on the cells:

In the above code:

  • On lines 15 through 17, we set the text of the cell's labelTitle to the name of the current map item.

Posting notification from Map Screen

Let's open LoadPlaces.swift file, and put the following code there:

In the above code:

  • On line 15, we initialize the notification center.

  • On line 43, we post the map items we fetched to the notification center.

Let's run the app again:

Great! We can see the search results!!! Now can we show the place on the map when we select it on the table view?

Code so far

53KB
Open

Last updated

Was this helpful?