 |
 |
Table view data source vs bindings (Cocoa)
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jul 2004
Status:
Offline
|
|
Hello,
I am currently trying to learn Cocoa. I have completed Steve Kochan's book on Objective-C and am now going through Hillegass's book on Cocoa, experimenting as I go along. I just have a quick question about bindings and NSTableView.
At the end of Chapter 5, after table views and their data sources were introduced, I played around and put together a very simple application that had a table view on the left and a text view on the right. The table view data source read a list of RTF files from the home directory (just by enumerating the directory and checking that the file extentsion isEqual: to "rtf" or "rtfd"). Then I used tableViewSelectionDidChange with readRTFDFromFile: to load a file into the text view whenever you click on one of the files in the table view. Pretty crude and simple, but I was pleased with it.
Anyway, I've just gone through Chapter 6, which is about bindings and sets up a table view in an app (RaiseMan) to use bindings to read, display and create its data (or model). This looks pretty powerful, but at this stage I haven't learned enough to know how I could use this method to set up an application similar to the one I created without bindings. Don't worry, I'm not asking how to do that - hopefully I'll get some idea as I progress further through the book. All I'd like to know is, would you generally always use bindings for this sort of thing, or would you ever use the way I described above? Is the data source method described in Chapter 5 the "old" way (pre-10.3), or are both methods used for different aplication requirements?
If somebody could clarify this I would be really grateful, as at this stage I'm a little confused.
Many thanks for any help,
KB
(Last edited by Ambit; Aug 2, 2004 at 01:41 PM.
)
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jul 2004
Status:
Offline
|
|
Hmm, I *think* I get it... Bindings are a quicker way of doing things, but there's no either/or, you would use *both*. ie. I could set up a table view using bindings and an NSArrayController, but then I would make that controller an outlet in my main class, set up a delegate to my class (or file's owner in a doc-based app), and then go about things the same way - ie. checking for a change in selection in the table and invoking methods accordingly using the delegate methods in my class...
Is this right, or am I way off the mark?
Many thanks,
KB
|
|
|
| |
|
|
|
 |
|
 |
|
Clinically Insane
Join Date: Oct 2001
Location: San Diego, CA, USA
Status:
Offline
|
|
I have to admit I'm somewhat less experienced with bindings than some, because the people I write for aren't 10.3-only, so I can only use bindings in my own personal tinkering around.
For probably 95% of cases, there is no reason not to use bindings other than backwards compatibility or masochism.
However, there are some cases that don't fit into Apple's premade bindings classes. For instance, it's possible to create a table view that doesn't have any underlying array. There could conceivably be some very interesting hocus-pocus under the hood to get the content for the table, and it might be necessary to use the old datasource methods. (I'm thinking maybe of some kind of database which uses C functions to get at the content, with some complex logic used in preparing the queries.)
|
|
Chuck
___
"Instead of either 'multi-talented' or 'multitalented' use 'bisexual'."
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jul 2004
Status:
Offline
|
|
Thanks for the helpful reply again Chuckit, much appreciated. I figured I would try to see how I could substitute bindings for some of the code I had done in my earlier test.
I think I managed to figure most of it out. I experimented, and managed to rewrite my test app (a table view displaying files that can be opened in a text view) using bindings, and less code. I set up an array controller and pointed it to my own array (a mutable array named "rtfFiles") in the myDocument class, then set up the text view and table view as outlets of the file's owner, with the file's owner as the delegate of the table view (ie. so that myDocument took control).
The only thing that has thrown me is sorting. It is very easy to set it up so that the table view resorts by clicking on its column header (using caseInsensitiveCompare: in IB), but what I hadn't anticipated is that sorting by clicking on the table column header only seems to resort the contents of the table - ie. the table view doesn't sort the underlying array that holds the data.
Thus, if on starting my app I click on the fifth table view item (index 4), which is titled "myfile.rtf", everything is fine and dandy - the correct file is opened in the text view. But then if I resort so that the list is in reverse order, and the fifth item is now listed as being "anotherfile.rtfd", if I click on it, it still opens "myfile.rtf" - because myfile.rtf still has an index of 4 in the underlying rtfFiles array, but no longer in the table view.
Am I missing something? I had assumed the NSArrayController would take care of this, but it seems that it does not. Am I missing a connection somewhere, or do I need to handle this in a didClickTableColumn:... delegate method or elsewhere? Obviously I need to make sure that my array is reshuffled to the same order as the display in the table view if I want to be able to use it to open text files.. I thought this might be covered later in the book, but looking through, I can't find anything about it, and couldn't find anything about it in the indices of Anguish or Davidson, or in the NSTableView documentation, either, even though it must be something that is very routine (and therefore no doubt something stupid that I am doing wrong because I'm new to Cocoa). I'm sure I could set up a comparison on the array to sort it when the table column is clicked, but what worries me is that eventually (ie. when I've learned much more) I would like to allow arbitrary resorting using drag'n'drop (admittedly a long way to go), and if the table view doesn't automatically resort the array, I can foresee this being a nightmare. But I am jumping waaay ahead of my current level there...
Thanks again,
KB
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jul 2004
Status:
Offline
|
|
Okay, I figured out a way of doing this, but I would really appreciate it if somebody could tell me whether this is the "correct way". As MyDocument (file's owner) is set up as the delegate of the table view, I just implemented this delegate method in MyDocument.h:
-(void) tableView: (NSTableView *) aTableView didClickTableColumn: (NSTableColumn *) tableColumn
{
[self setRtfFiles: [rtfController arrangedObjects]];
}
rtfFiles is a mutable array that is set as the content of an NSArrayController; rtfController is an IBOutlet pointing to that NSArrayController. Thus, whenever the the table view is resorted, the above method is called to set the source array to the sorted version of the array, which means if I click on one, the correct text file is opened.
EDIT: the other way I have implemented this (as an alternative to using the above delegate message) is to use [rtfController arrangedObjects] instead of the rtfFiles array when using objectAtIndex and the row number to access an object... This is probably the quickest way I have found of doing it...
Is this the correct way of doing this, or have I missed a binding somewhere between my source array and my array controller?
Many thanks for any info,
KB
(Last edited by Ambit; Jul 31, 2004 at 06:13 PM.
)
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jul 2004
Status:
Offline
|
|
Sorry to be a pain by posting in my own thread again, but after getting everything working, I've noticed that Xcode has crashed a couple of times over the past couple of days, usually when opening a file (the test project I was working on). I looked at Xcode's crash log, and it brought up another crash log that said something about there being two objects at "path" after it being deallocated, and "this may be a memory leak". As I use the local variable "path" in the test app I was discussing above, I guess this must be the cause, but I am a loss to find the memory leak, because I am using NSString methods that should put everything into the autorelease pool, and I release any temporary objects myself. Even stranger, my application itself isn't crashing, only Xcode - even if I've run my app *outside* of Xcode (ie. directly from the build directory). Here are the only two methods that use a "path" variable (both from MyDocument.m):
Code:
// Called from MyDocument's init override:
-(void) listFiles
{
// Get all .rtf or .rtfd files in the home directory and store them in the rtfFiles array:
NSString *path = NSHomeDirectory(); // previously using: [NSString stringWithString: NSHomeDirectory()];
NSArray *filesArray = [[NSFileManager defaultManager] directoryContentsAtPath: path];
HemDoc *newDoc; // HemDoc is a test class that just contains an NSString instance variable called "title"
int i;
rtfFiles = [[NSMutableArray alloc] initWithCapacity: 10]; // rtfFiles is a mutable array instance variable of MyDocument
for (i = 0; i < [filesArray count]; ++i)
{
if (
([[[filesArray objectAtIndex: i] pathExtension] isEqual: @"rtf"])
||
([[[filesArray objectAtIndex: i] pathExtension] isEqual: @"rtfd"])
)
{
newDoc = [[HemDoc alloc] init];
[newDoc setTitle: [filesArray objectAtIndex: i]];
[rtfFiles addObject: newDoc]; // add object retains the objects for the lifetime of rtfFiles
[newDoc release];
}
}
}
// TABLE VIEW DELEGATE METHOD
-(void) tableViewSelectionDidChange: (NSNotification *) notification
{
NSString *path = NSHomeDirectory(); // previously using: [NSString stringWithString: NSHomeDirectory()];
NSString *fullPath;
int row = [tableView selectedRow];
if (row != -1) // not out of bounds
{
fullPath = [path stringByAppendingPathComponent: [[[rtfController arrangedObjects] objectAtIndex: row] title]];
[textView readRTFDFromFile: fullPath];
}
}
Is there any obvious memory leakage here? Sorry if I am missing something stupid, and many thanks to anybody who can be bothered to scan through these few lines of code.
Thank you,
KB
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jul 2004
Status:
Offline
|
|
Sorry to be a pain, but does anybody have any ideas on this? In the code above, now that I've changed NSString *path = [NSString stringWithString: NSHomeDirectory()] to NSString *path = NSHomeDirectory() the crashes seem to have ceased, but I don't quite understand why (and as I say, the crashes were in Xcode, not in my app). I'd really like to understand the significance of this so that I can avoid writing buggy programs...
Many thanks,
KB
|
|
|
| |
|
|
|
 |
 |
|
 |
|
|
|
|
|

|
|
 |
Forum Rules
|
 |
 |
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
 |
 |
 |
 |
|
 |
|