title: Implementing Spotlight feature using NSMetaDataQuery and NStableView Data Source Method
body: <p>I have implemented spotlight feature in my project using <code>NSMetadataQuery</code>. On receiving <code>NSMetadataQueryDidFinishGatheringNotification</code> Notification I am calling reloadData method of tableView method after formatting the <code>NSMetadataItem</code> of <code>NSMetadataQuery</code>. I am facing below two issues.</p>
  
  <ol>
  <li><code>[query startQuery]</code> is taking too much time when there is huge data in mac.</li>
  <li>Not getting <code>NSMetadataQueryDidUpdateNotification</code>;</li>
  </ol>
  
  <p>Search is fast when I ma using <code>NSArrayController</code> instead of <code>NStableViewDataSource</code> and binding it with <code>query.results</code>. As I need to format the  <code>NSMetadataItem</code> so i can't use it.</p>
  
  <p>Can anyone answer how to receive batch notification for better performance of <code>NSMetaDataQuery</code>. or any other way to improve the performance of <code>[query startQuery]</code></p>
  
  <p>Below is code which I have implemented. </p>
  
  <pre><code>- (void)initiateSearch:(NSString *)seString
  {
      self.metadataSearch=[[[NSMetadataQuery alloc] init] autorelease];
  
      [[NSNotificationCenter defaultCenter] addObserver:self
                                               selector:@selector(queryDidUpdatesfsdf:)
                                                   name:NSMetadataQueryDidUpdateNotification
                                                 object:metadataSearch];
  
      [[NSNotificationCenter defaultCenter] addObserver:self
                                               selector:@selector(initalGatherComplete:)
                                                   name:NSMetadataQueryDidFinishGatheringNotification
                                                 object:metadataSearch];
  
        NSArray *terms = [seString componentsSeparatedByString:@","];
      NSMutableArray  *pridicateArray = [NSMutableArray array];
      NSPredicate *searchPredicate;
      for(NSString *term in terms) {
          if([term length] == 0)
          {
              continue;
          }
          NSString *trimmedString = [[NSString alloc] initWithFormat:@"*%@*",[term stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
          NSPredicate *p = [NSPredicate predicateWithFormat:@"(kMDItemFSName like[cd] %@)",trimmedString];
          [pridicateArray addObject:p];
          [trimmedString release];
  
      }
  
      if ([pridicateArray count] == 1) {
          searchPredicate= [pridicateArray objectAtIndex:0];
      }
      else
      {
          searchPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:pridicateArray];
      }
      [metadataSearch setPredicate:searchPredicate];
  
      NSArray *searchScopes;
      searchScopes=[NSArray arrayWithObjects:NSMetadataQueryUserHomeScope,nil];
      [metadataSearch setSearchScopes:searchScopes];
  
      NSSortDescriptor *sortKeys=[[[NSSortDescriptor alloc] initWithKey:(id)kMDItemDisplayName
                                                              ascending:YES] autorelease] ;
      [metadataSearch setSortDescriptors:[NSArray arrayWithObject:sortKeys]];
  
      [metadataSearch setNotificationBatchingInterval:5.0];
  
      [metadataSearch startQuery];
  }
  
  - (void)queryDidUpdatesfsdf:sender;
  {
      NSLog(@"A data batch has been received");
  }
  
  
  - (void)initalGatherComplete:sender;
  {
      [metadataSearch stopQuery];
  
      p_Thread = [[NSThread alloc] initWithTarget:self selector:@selector(dosome:) object:metadataSearch];
  
      [p_Thread start];
  
      [[NSNotificationCenter defaultCenter] removeObserver:self
                                                      name:NSMetadataQueryDidUpdateNotification
                                                    object:metadataSearch];
      [[NSNotificationCenter defaultCenter] removeObserver:self
                                                      name:NSMetadataQueryDidFinishGatheringNotification
                                                    object:metadataSearch];
  
  }
  
  -(void)dosome: (NSMetadataQuery *)metadataresult
  {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  
      NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
      [dateFormatter setDateFormat:@"MM/dd/yyyy HH:mm:ss"];
  
      fileListArray = [[NSMutableArray alloc] init];
      [fileListArray removeAllObjects];
      NSUInteger i=0;
      for (i=0; (i &lt; [metadataresult resultCount] &amp;&amp; ![p_Thread isCancelled]); i++) {
          NSMetadataItem *theResult = [metadataresult resultAtIndex:i];
          NSString *displayName = [theResult valueForAttribute:(NSString *)kMDItemFSName];
          NSString *displayPath = [theResult valueForAttribute:(NSString *)kMDItemPath];
          NSString *fileSize = [theResult valueForAttribute:(NSString *)kMDItemFSSize];
  
  
          FileList *fileList = [[FileList alloc] init];
          [fileList setName:displayName];
          [fileList setIsChecked:NO];
          [fileList setPath:displayPath];
          [fileList setLastModified:[dateFormatter stringFromDate:[theResult valueForAttribute:(NSString *)kMDItemContentModificationDate]]];
          [fileList setFileSize:[IBUtility formatedFileSizeForOutlineView:fileSize]];
          [fileList setMSize:[fileSize longLongValue]];
          [[self fileListArray] addObject:fileList];
  
          if (i%50 == 0  &amp;&amp; ![p_Thread isCancelled]) {
              [searhFinderTableView performSelectorOnMainThread:@selector(reloadData) withObject:Nil waitUntilDone:YES];
          }
      }
      self.metadataSearch=nil;
  
      if ([[self fileListArray] count] == 0) {
          [mSearchingLabel setStringValue:@"Items not found"];
  
          NSRect textFieldFrame = [mSearchingLabel frame];
  
          [mSearchingLabel setFrame:NSMakeRect(mContinuousProgress.frame.origin.x,textFieldFrame.origin.y, textFieldFrame.size.width,textFieldFrame.size.height)];
      }
      else if(![p_Thread isCancelled])
      {
          [searhFinderTableView performSelectorOnMainThread:@selector(reloadData) withObject:Nil waitUntilDone:YES];
          [mSearchingLabel setHidden:YES];
      }
  
      [mContinuousProgress stopAnimation:self];
      [dateFormatter release];
  
      [pool release];
  
  }
  - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
  {
      return [fileListArray count];
  
  }
  
  
  - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
  {
      FileList *fileList = [fileListArray objectAtIndex:rowIndex];
  
      if ([[aTableColumn identifier] isEqualToString:@"filePath"])
      {
          return [fileList valueForKey:@"path"];
      }
      else if([[aTableColumn identifier] isEqualToString:@"isSelected"])
      {
          return [NSNumber numberWithBool:fileList.isChecked];
      }
      else if([[aTableColumn identifier] isEqualToString:@"fileSize"])
      {
          return [fileList valueForKey:@"fileSize"];
      }
      else if([[aTableColumn identifier] isEqualToString:@"lastModified"])
      {
          return [fileList valueForKey:@"lastModified"];
      }
      return nil;
  }
  </code></pre>