如何在iOS中实现类似Gmail的搜索功能(含建议、分段控件等)
Let’s break down how to build each of your required features step by step, with extra context for table view basics since you mentioned being new to them.
1. Set Up the Search Bar & Segmented Control View
First, we’ll create a dedicated view controller to hold the segmented control and table view for search results/suggestions.
Create the Search Results View Controller
- Make a new
UIViewControllersubclass calledSearchResultsViewController. - Add a
UISegmentedControlto the top (e.g., with options like "Inbox", "All Mail", "Sent") and pin it to the top edges of the view. - Add a
UITableViewbelow the segmented control, pinning it to the segmented control’s bottom and the view’s bottom/left/right edges so it fills the remaining space. - Connect the table view to an IBOutlet named
resultsTableView, and set its data source/delegate to the view controller (either via Interface Builder or code).
Integrate the Search Controller in Your Main View Controller
In your main inbox view controller, set up a UISearchController to present the SearchResultsViewController when the search bar is tapped:
import UIKit class MainInboxViewController: UIViewController { private let searchResultsVC = SearchResultsViewController() private lazy var searchController: UISearchController = { let controller = UISearchController(searchResultsController: searchResultsVC) controller.searchBar.placeholder = "Search mail" controller.obscuresBackgroundDuringPresentation = false return controller }() override func viewDidLoad() { super.viewDidLoad() navigationItem.searchController = searchController definesPresentationContext = true // Pass your full list of emails to the results controller searchResultsVC.allEmails = yourFullEmailArray } }
Now, tapping the search bar will show your segmented control and empty table view.
2. Implement Search Suggestions & Navigation
Next, let’s add the search suggestions list that navigates to a results view when tapped.
Add Suggestions Data
In SearchResultsViewController, define arrays to hold your suggestions and filtered results:
// Custom model for your emails (adjust fields to match your data) struct Email { let subject: String let sender: String let content: String } class SearchResultsViewController: UIViewController { @IBOutlet weak var resultsTableView: UITableView! @IBOutlet weak var searchSegmentedControl: UISegmentedControl! var allEmails: [Email] = [] var searchSuggestions: [String] = ["Important emails", "Unread", "Sent today", "From: John"] var filteredSuggestions: [String] = [] var filteredEmails: [Email] = [] var currentSearchText: String = "" override func viewDidLoad() { super.viewDidLoad() // Register a reusable cell for the table view resultsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "SearchCell") } }
Update Suggestions as User Types
Conform to UISearchResultsUpdating to react to search text changes:
extension SearchResultsViewController: UISearchResultsUpdating { func updateSearchResults(for searchController: UISearchController) { guard let searchText = searchController.searchBar.text?.lowercased() else { return } currentSearchText = searchText // Filter suggestions to match the search text filteredSuggestions = searchSuggestions.filter { $0.lowercased().contains(searchText) } // Filter emails based on subject or sender (adjust to your needs) filteredEmails = allEmails.filter { $0.subject.lowercased().contains(searchText) || $0.sender.lowercased().contains(searchText) } // Reload the table view to show updated data resultsTableView.reloadData() } }
Don’t forget to link the search updater in your main view controller’s viewDidLoad:
searchController.searchResultsUpdater = searchResultsVC
Configure Table View for Suggestions & Results
Implement the table view data source methods to show the right content based on the segmented control:
extension SearchResultsViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch searchSegmentedControl.selectedSegmentIndex { case 0: // Suggestions tab return filteredSuggestions.isEmpty ? 1 : filteredSuggestions.count case 1: // All Mail results return filteredEmails.isEmpty ? 1 : filteredEmails.count default: return 0 } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SearchCell", for: indexPath) switch searchSegmentedControl.selectedSegmentIndex { case 0: if filteredSuggestions.isEmpty { cell.textLabel?.text = "No suggestions found" cell.textLabel?.textColor = .gray } else { cell.textLabel?.text = filteredSuggestions[indexPath.row] cell.textLabel?.textColor = .black } case 1: if filteredEmails.isEmpty { cell.textLabel?.text = "No emails found" cell.textLabel?.textColor = .gray } else { let email = filteredEmails[indexPath.row] cell.textLabel?.text = email.subject cell.detailTextLabel?.text = email.sender } default: cell.textLabel?.text = "" } return cell } }
Handle Tap Navigation
Add the table view delegate method to navigate when a suggestion or result is tapped:
extension SearchResultsViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) switch searchSegmentedControl.selectedSegmentIndex { case 0: guard !filteredSuggestions.isEmpty else { return } let selectedSuggestion = filteredSuggestions[indexPath.row] // Navigate to a results view controller with the selected search term let resultsVC = EmailResultsViewController() resultsVC.searchTerm = selectedSuggestion navigationController?.pushViewController(resultsVC, animated: true) case 1: guard !filteredEmails.isEmpty else { return } let selectedEmail = filteredEmails[indexPath.row] // Navigate to the email detail view let detailVC = EmailDetailViewController() detailVC.email = selectedEmail navigationController?.pushViewController(detailVC, animated: true) default: break } } }
3. Table View Basics Recap
Since you’re new to table views, here are key concepts to remember:
- DataSource: Mandatory methods that tell the table view how many rows to show (
numberOfRowsInSection) and what content goes in each cell (cellForRowAt). - Delegate: Handles user interactions (like taps) and customizations (cell heights, headers).
- Cell Reuse: Always use
dequeueReusableCellto avoid creating new cells every time—this keeps your app performant.
Bonus Tips
- Debounce Search: If fetching suggestions from a backend, add a 300ms delay before making API calls to avoid excessive requests as the user types.
- Highlight Matches: Add code to highlight the part of the text that matches the search term in table view cells for better readability.
- Empty States: Show friendly messages (like we did) when no results or suggestions are found, instead of leaving the table blank.
内容的提问来源于stack exchange,提问作者Nikita Patil

