Swift NSSearchField NSTableView Sample Code

Swift NSSearchField NSTableView Sample Code

Created By:Debasis Das (May 2016)

In this post we will discuss the most lengthy way to implement a NSSearchField and tie the same to a NSTableView.

Earlier we have discussed two alternate ways to achieve the same functionality

Approach 1 http://www.knowstack.com/swift-nssearchfield-nstableview-with-bindings/ In this article we had achieved the same functionality using bindings. This approach is the simplest and least amount of coding is required. however things becomes tricky when columns are created dynamically

Approach 2: http://www.knowstack.com/swift-nssearchfield-nsarraycontroller-no-bindings/ In this article we have used an NSArrayController to hold the backup data prior to filtering.

In Approach 3 we will implement everything through code.

//  AppDelegate.swift
//  NSSearchField_NSTableView_Programatically
//  Created by Debasis Das on 27/05/16.
//  Copyright © 2016 Knowstack. All rights reserved.

import Cocoa

class AppDelegate: NSObject, NSApplicationDelegate, NSTableViewDelegate,NSTableViewDataSource {
//The app delegate is the table view delegate and datasource
    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var tableView: NSTableView!
    @IBOutlet weak var searchField:NSSearchField!

    var contacts:[Person] = [] //The contacts array
    var backUpContacts:[Person] = [] //The backup array to hold the original list
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        for item in self.dataArray(){
            self.contacts.append(item as! Person)
        self.backUpContacts = self.contacts //Creating a backup of the contacts. Ideally the backup list should be populated from the find method that fetches records from a database

    func createMenuForSearchField(){
        let menu = NSMenu()
        menu.title = "Menu"
        let allMenuItem = NSMenuItem()
        allMenuItem.title = "All"
        allMenuItem.target = self
        allMenuItem.action = #selector(AppDelegate.changeSearchFieldItem(_:))
        let fNameMenuItem = NSMenuItem()
        fNameMenuItem.title = "First Name"
        fNameMenuItem.target = self
        fNameMenuItem.action = #selector(AppDelegate.changeSearchFieldItem(_:))
        let lNameMenuItem = NSMenuItem()
        lNameMenuItem.title = "Last Name"
        lNameMenuItem.target = self
        lNameMenuItem.action = #selector(AppDelegate.changeSearchFieldItem(_:))

        self.searchField.searchMenuTemplate = menu

    func changeSearchFieldItem(sender:AnyObject){
    //Based on the Menu item selection in the search field the placeholder string is set
        (self.searchField.cell as? NSSearchFieldCell)?.placeholderString = sender.title
    func numberOfRowsInTableView(tableView: NSTableView) -> Int {
        return self.contacts.count
    func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? {
        let identifier = tableColumn?.identifier
        let str = self.contacts[row].valueForKey(identifier!)
        return str
    func tableView(tableView: NSTableView, setObjectValue object: AnyObject?, forTableColumn tableColumn: NSTableColumn?, row: Int) {
        self.contacts[row].setValue(object, forKey: (tableColumn?.identifier)!)
    func dataArray()->NSMutableArray{
        let arr = NSMutableArray()
        arr.addObject(Person.createPerson("Debasis", lName: "Das"))
        arr.addObject(Person.createPerson("John", lName: "Doe"))
        arr.addObject(Person.createPerson("Jane", lName: "Doe"))
        return arr

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application

    override func controlTextDidChange(obj: NSNotification) {
        if obj.object === self.searchField{
            let searchString = self.searchField.stringValue
            var predicate:NSPredicate = NSPredicate()
            if searchString.isEmpty{
                self.contacts = self.backUpContacts
                if (self.searchField.cell as? NSSearchFieldCell)?.placeholderString == "All"{
                    predicate = NSPredicate(format: "firstName contains %@ OR lastName contains %@ ",searchString,searchString)
                else if (self.searchField.cell as? NSSearchFieldCell)?.placeholderString == "First Name"{
                predicate = NSPredicate(format: "firstName contains %@",searchString)
                else if (self.searchField.cell as? NSSearchFieldCell)?.placeholderString == "Last Name"{
                    predicate = NSPredicate(format: "lastName contains %@",searchString)
                self.contacts = (self.backUpContacts as NSArray).filteredArrayUsingPredicate(predicate) as! [Person]


class Person:NSObject{
    var firstName:String = ""
    var lastName:String = ""
    class func createPerson(fName:String, lName:String)->Person{
        let person = Person()
        person.firstName = fName
        person.lastName = lName
        return person

Swift NSSearchField NSTableView Sample Code 2

Swift NSSearchField NSTableView Sample Code 1


You can download the sample code from NSSearchField_NSTableView_Programatically

Posted in Swift Tagged with: , ,
2 comments on “Swift NSSearchField NSTableView Sample Code
  1. Sarath says:

    How is the search results displayed in Mail,Finder etc? Which control is used for it?

Leave a Reply

Your email address will not be published. Required fields are marked *