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

@NSApplicationMain
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
        self.tableView.setDataSource(self)
        self.tableView.setDelegate(self)
        
        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
        self.tableView.reloadData()
        
        self.createMenuForSearchField()
    }

    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(_:))

        
        menu.addItem(allMenuItem)
        menu.addItem(fNameMenuItem)
        menu.addItem(lNameMenuItem)
        
        self.searchField.searchMenuTemplate = menu
        self.changeSearchFieldItem(allMenuItem)

    }
    
    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
            }
            else{
                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]
            }
            self.tableView.reloadData()
        }
    }


}

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: , ,

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news