NSOutlineView won't reload data on keydown, but updates on focus

I've been trying to figure this issue out for the last couple of hours with a lot of searching involved and watching videos. Here's what I'm trying to do:

Summary : A simple window allowing me to move a message from my inbox to any of my many mail folders. As I type the name of the mail folder I'm looking for, the outline view should automatically refresh only displaying the ones with the matching text - think MsgFiler if you know it.

  • Type text in text box
  • As I type each letter, I want the NSOutlineView to update it's data to have less and less folders that match my input text. (At the moment, my test just adds a "Test Mailbox" into the NSOutlineView
  • Current result :

  • Type text in text box
  • Nothing happens
  • Click the NSOutlineView, the view gets updated
  • TextfieldDelegate.m:

    #import "TextFieldDelegate.h"
    #import "OutlineViewController.h"
    #import "GetMailDatasource.h"
    
    @implementation TextFieldDelegate
    
    @synthesize testLabel;
    
    - (void) controlTextDidChange :(NSNotification *) sender {
      NSTextField *changedField = [sender object];
      NSLog(@"in control text did change");
    
      //Just some text code to see the change when text does change
      NSString *text = [changedField stringValue];
      [testLabel setStringValue:text];
    
      NSLog(@"changed the label and creating the data now");
    
      OutlineViewController *vc = [[OutlineViewController alloc] init];
      [vc refreshTheData:sender];
      [vc.outlineView reloadData];
      [vc release];
    }
    
    - (void)controlTextDidEndEditing:(NSNotification *)obj {
      NSLog(@"in end editting");
      return;
    }
    
    @end
    

    OutlineViewController.m

    #import "OutlineViewController.h"
    #import "GetMailDatasource.h"
    
    @implementation OutlineViewController
    
    - (id) init {
    
      self = [super init];
      if (self) {
        _mailboxes = [[NSMutableArray alloc] init];
        if (myMailboxes != nil) {
            _mailboxes = myMailboxes;
        } else {
            GetMailDatasource *mailDatasource = [[GetMailDatasource alloc] init];
            [mailDatasource createFakeData];
            _mailboxes = myMailboxes;
        }
      }
    
      NSLog(@"inited outline view controller");
      return self;
    }
    
    - (IBAction) refreshTheData : (id) sender {
    
      NSLog(@"in refreshTheData");
    
      Mailbox *m = [self.outlineView itemAtRow:[self.outlineView selectedRow]];
      if (m)
         [m addChild:[[Mailbox alloc] init]];
      else
          [self.mailboxes addObject:[[Mailbox alloc] init]];
    
      NSLog(@"running reloadData");
      [self.outlineView reloadData];
    }
    
    #I know these work, but providing them for completeness
    #pragma mark NSOutlineView Data Source Methods
    
    - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
        return !item ? [self.mailboxes count] : [[ item children] count ];
    }
    
    - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
        return !item ? YES : [[item children ] count] != 0;
    }
    
    - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
        return !item ? [self.mailboxes objectAtIndex:index] : [[item children] objectAtIndex:index];
    }
    
    - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
        return [item name];
    }
    
    @end
    

    I do have a separate "Test Button" that I added on the interface just to try out and I've bound it's "Sent action" directly to the "refreshTheData" function on the OutlineViewController and that works without a hitch. Adds the new item in the NSOutlineView and it updates immediately.

    I'm not sure what else is required to try to figure out where the problem lies... Any suggestions would be much appreciated!

    Many thanks!


    You create a new instance every time controlTextDidChange. So you change the settings of this OutlineViewController and than release it.

    Instead of this you should use the outline view on screen.


    Resolved it.

    So, I already had the outline view in IB and an object for the OutlineViewController in IB. I even tried referencing the new method "refreshTheData" in my controller by using the OutlineView object I had associated to my TextFieldDelegate. That's where I was wrong.

    What I needed to do was associate the OutlineViewController itself to my TextFieldDelegate, then I could call "refreshTheData" with the appropriate links in the IB interface.

    So, finally, the code looks like this, changes highlighted like this -->:

    TextFieldDelegate.h

    #import <Foundation/Foundation.h>
    --> #import "OutlineViewController.h"
    
    @interface TextFieldDelegate : NSObject {
        IBOutlet OutlineViewController *outlineView;
    }
    
    @property (nonatomic, strong) IBOutlet NSTextField * testLabel;
    @property (nonatomic, strong) IBOutlet NSTextField * userInput;
    
    - (IBAction) controlTextDidChange :(id) sender;
    

    @end

    And this now allows TextFieldDelegate.m's code, get recognised:

    - (void) controlTextDidChange :(NSNotification *) sender {
        NSTextField *changedField = [sender object];
    
        NSString *text = [changedField stringValue];
        [testLabel setStringValue:text];
    
        --> [outlineView refreshTheData:sender];
    }
    

    The highlighted line always suggested that it could not recognise that method because I was trying to use it on the actual NSOutlineView item, not it's delegate where I created the method. I had thought that by hooking up the delegate to the NSOutlineView, they would either become one and the same, or that the method would be find via transitivity sort of.

    Thanks for the pointers @Amin, it helped me get there in the end.

    链接地址: http://www.djcxy.com/p/85214.html

    上一篇: 'NSFormatter'有多少隐约的子类? 知道其他人吗?

    下一篇: NSOutlineView将不会重新加载keydown上的数据,而是重点更新