iOS App Development iOS8

Parse search in iOS 8 with Swift

I have been getting a lot of requests to show how to implement Parse search functionality uing Swift.Previously I had shown how to implement search : UISearchBar and UISearchBarDelegate if you haven’t checked that before I suggest you to take a look at it to get an overall idea.

Lets dive directly into code and I will explain what it does. Most of the code is boilerplate code for UITableViewController. The main function is to take the search text and implement the search functionality. In this case we would ideally want the search to be done on the server side and not client side hence we make use of the where key for containsString in the PFQuery class to perform search on server side and return the results.

//
//  ParseSearchTableViewController.swift
//  SwiftSearch
//
//  Created by Shrikar Archak on 3/31/15.
//  Copyright (c) 2015 Shrikar Archak. All rights reserved.
//

import UIKit

class ParseSearchTableViewController: UITableViewController, UISearchBarDelegate {


    @IBOutlet weak var searchBar: UISearchBar!
    var searchActive : Bool = false
    var data:[PFObject]!
    var filtered:[PFObject]!
    override func viewDidLoad() {
        super.viewDidLoad()

        searchBar.delegate = self
        /* Add some data */
//        for index in 1...10{
//            let obj = PFObject(className: "SearchText")
//            obj["text"] = "Text here \(index)"
//            obj.save()
//        }
        search()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func search(searchText: String? = nil){
        let query = PFQuery(className: "SearchText")
        if(searchText != nil){
            query.whereKey("text", containsString: searchText)
        }
        query.findObjectsInBackgroundWithBlock { (results, error) -> Void in
            self.data = results as? [PFObject]
            self.tableView.reloadData()
        }

    }


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

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if(self.data != nil){
            return self.data.count
        }
        return 0
    }


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        let obj = self.data[indexPath.row]
        cell.textLabel!.text = obj["text"] as? String
        return cell
    }

    func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
        searchActive = true;
    }

    func searchBarTextDidEndEditing(searchBar: UISearchBar) {
        searchActive = false;
    }

    func searchBarCancelButtonClicked(searchBar: UISearchBar) {
        searchActive = false;
    }

    func searchBarSearchButtonClicked(searchBar: UISearchBar) {
        searchActive = false;
    }

    func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
        search(searchText: searchText)
    }
}

If the amount of data you are searching is small this approach might be ok, but this is not ideal for full text search. You can also take a look at this blog post http://blog.parse.com/2013/03/19/implementing-scalable-search-on-a-nosql-backend/ for understanding how it can be done efficiently

About the author

Shrikar

Backend/Infrastructure Engineer by Day. iOS Developer for the rest of the time.

  • Blake Allen

    Heads up, the Html autoformatted the -> to a -gt in the code example

  • Sidney

    Not a good aproach. If the amount of data is not huge you can search through your ‘data’array instead of using Parse to make requests every time your user type something different.

/* ]]> */