macosnsmutablearraynstableviewnssearchfield

How to do searching in NSTableView with NSSearchField?


I have implemented a application in which I use NSTableview with the help of its data source and delegates I have not used NSArrayController nor I want to use it. My question is how can I bind NSSearchField with my NSTableView in this situation? I had seen a lot of answer using NSArrayController. I do not want to convert implementation to NSArrayController as things are working good with NSMutableArray.


Solution

  • TableView is a display control and is not for filtering. You should add 2 NSArray properties;
    1) @property(nonatomic, strong) NSArray *allItems;
    2) @property(nonatomic, strong) NSArray *filteredItems;

    #import "ViewController.h"
    
    @interface ViewController()<NSSearchFieldDelegate, NSTableViewDelegate, NSTableViewDataSource>
    
    // Your NSSearchField
    @property (weak) IBOutlet NSSearchField *searchField;
    
    // Your NSTableView
    @property (weak) IBOutlet NSTableView *tableView;
    
    // In this array you will store all items
    @property(nonatomic, strong) NSArray *allItems;
    
    // In this array you will store only filtered items
    @property(nonatomic, strong) NSArray *filteredItems;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.searchField.delegate = self;// You can set delegate from XIB/Storyboard
        self.tableView.delegate = self;// You can set delegate from XIB/Storyboard
        self.tableView.dataSource = self;// You can set dataSource from XIB/Storyboard
    
        self.allItems = @[@"Test1", @"Demo filter", @"Test 2", @"Abracadabra"];
        [self applyFilterWithString:@""];
    }
    
    - (void)controlTextDidChange:(NSNotification *)obj{
    
        if (obj.object == self.searchField) {
            [self applyFilterWithString:self.searchField.stringValue];
        }
    }
    
    -(void)applyFilterWithString:(NSString*)filter {
    
        if (filter.length>0) {
            NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"self CONTAINS[cd] %@", filter];
            self.filteredItems = [self.allItems filteredArrayUsingPredicate:filterPredicate];
        }
        else {
            self.filteredItems = self.allItems.copy;
        }
        [self.tableView reloadData];
    }
    
    #pragma mark - ***** NSTableViewDataSource, NSTableViewDelegate *****
    
    - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
        return self.filteredItems.count;
    }
    
    
    // for the "Cell Based" TableView
    - (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row {
    
        NSString *item = self.filteredItems[row];
        return item;
    }
    
    @end