1
votes

I'm having a problem getting my table views to display the data from the datasource. Hope someone can point me in the right direction here.

In IB I have two table views, I set their tags to 1 and 2 respectively. I also have a AppController object and have connected the two tables to that for datasource and delegate.

The app works by a user clicking a button, which runs a method in AppController.m that allows the user to navigate to a directory and select it, the method then gets all the filenames in that directory and then filters for .tif and .eps files. Pretty basic stuff. Here's that method.

//allows the user to select a folder to read and filter for acceptable image files (eps, tif)
- (IBAction) getFileNames : (id) sender { 

//clear out file list
if ([fileList count] > 0) { 
    [fileList removeAllObjects];
}

// Create the File Open Dialog class.
NSOpenPanel* openDlg = [NSOpenPanel openPanel];

// Enable the selection of files in the dialog.
[openDlg setCanChooseFiles:YES];

// Enable the selection of directories in the dialog.
[openDlg setCanChooseDirectories:YES];

// Display the dialog.  If the OK button was pressed,
if ( [openDlg runModalForDirectory:nil file:nil] == NSOKButton ) {

    // Get an array containing the full filenames of all
    // files and directories selected.
    NSArray* files = [openDlg filenames];

    // Loop through all the files and process them. (Hopefully most of the time Mark will be selecting just the archive directory on storage server)
    for(int  i = 0; i < [files count]; i++ ) {
        //make string of object path
        NSString* objPath = [files objectAtIndex:i];

        //determine if object is a directory or file
        //create a file manager
        NSFileManager* fileManager = [[NSFileManager alloc] init];

        //set a bool
        BOOL isDir; 

        //check to see if the object is a folder
        if ([fileManager fileExistsAtPath:objPath isDirectory:&isDir] && isDir) { 

            //set the fileList array


            //if it is a directory then read the contents of the directory and display in the file list table
            NSError* dirErr; 
            NSMutableArray *rawFileList = (NSMutableArray *)[[NSFileManager defaultManager] contentsOfDirectoryAtPath:objPath error:&dirErr];

            //loop through file list and get the file type, if it is a .eps or .tif then move it to fileList
            for(int f=0; f<[rawFileList count]; f++) { 

                //set an NSString 
                NSString* thisFile = [rawFileList objectAtIndex:f];

                //filter out any file that does not have a .tif or .eps extension
                if ([thisFile rangeOfString:@".eps"].location != NSNotFound || [thisFile rangeOfString:@".eps"].location != NSNotFound) {
                    //add correct files to fileList arrays
                    [fileList addObject:thisFile];
                }

                //use core graphics to get the meta data of the file and determine if it is an eps or tif file
                /*CGImageSourceRef source = CGImageSourceCreateWithURL( (CFURLRef) URL, NULL);
                NSDictionary* metadata = (NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source,0,NULL);*/
            }

            NSLog(@"%i:::", [fileList count]);

            //dump file list into NSTable

        } else { 
            NSLog(@"nope, this is a file");
        }
    }
}

}

When I log the count of items in the array fileList I am getting 118. However, when I log fileList in the table methods I get 0. I expect that when the app "awakes" but after fileList is sent objects shouldn't it change? I know the NSTableViews are connected properly (see code below) in IB as I can hard code a number in numberOfRowsInTableView method and hard code a string in the tableView method and they work. They just won't work with my array.

- (int)numberOfRowsInTableView:(NSTableView *)t {

NSLog(@"%i", [fileList count]);
return [fileList count];
}

 - (id)tableView:(NSTableView *)t objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row {
   // return [fileList objectAtIndex:row];

if ([t tag] == 1) { 
    return [fileList objectAtIndex:row];
} else { 
    return @"table 2"; 
}

return 0; 
} 

I'm a little fuzzy on how delegates work but from the docs this seems to be similar to AppleScript's idle event, where the controller and the objects are communicating to each other any changes that are occurring. Do I have to declare file list as the array to watch?

1

1 Answers

3
votes

The NSTableView objects aren't actively looking for changes to the underlying data model, so if you change the data model (in your case the fileList array), then you need to tell the table view that it has changed. You can call -(void)reloadData on the table view after you have loaded up your files, and it should use the new data in fileList.

You can also use bindings to connect the tableview, and then it will get notified when you update the property it is bound to (more info here and a good tutorial here).