Re: Display csv in a tableView with bindings

2009-07-26 Thread Aaron Burghardt


On Jul 26, 2009, at 5:38 PM, I. Savant wrote:


On Jul 26, 2009, at 3:52 PM, Aaron Burghardt wrote:

Not necessarily.  If the keys are NSStrings, then they are copied  
when added to the dictionary, but a copy of an immutable string is  
optimized to just retain it, so the data isn't duplicated (assuming  
all rows have the same columns in the same order, an assumption you  
don't seem to be making).


 Actually, I temporarily take back my "you're probably right"  
response. :-) I can't find a reference to this anywhere, but I  
admittedly only looked in the NSString API reference, the  
Introduction to Strings Programming Guide for Core Foundation and  
quickly perused the The Objective-C 2.0 Programming Language.


 Would you mind directing me to where this is stated? I'm not saying  
you're wrong - it sounds plausible - I'm just not sure you're  
right. :-)




I didn't think it was documented anywhere, but Adam found a reference  
for at least some forms.  But, it's well-known on the list and easy to  
test (see example below).  Caveat: it's an implementation detail that  
you normally shouldn't be concerned with.  But, if you get to the  
point that you need to optimize memory consumption, it is worthwhile  
to confirm the behavior.  For example, if you pass mutable strings to  
the method that parses the CSV, then you need to make immutable copies  
first.


Keep in mind that an NSArrayController created in Interface Builder  
is defined by default to create an NSMutableDictionary for each  
item in the dictionary.


 With respect, I don't see how this is relevant to my point.


It was an unnecessary point.  I was interpreting your comments to be  
strongly advocating not using dictionaries, and I was trying to  
suggest it is more common than that.


It's not unreasonable, and we don't know the OP's performance  
requirements.




 No, it's not unreasonable, but since we don't know the OP's  
performance requirements, the original blanket statement that  
NSDictionary is better won't do without these caveats (ie, "it's  
easier for bindings, but dog-slow on reasonably large files").  
Rather than just say "there's more to it than that" as a drive-by  
correction, I wanted to provide a helpful explanation and  
workaround, since this is an area in which I have recent and  
detailed experience. :-)


You brought up some good discussion points, and I probably should have  
asked the OP to give us more details.  I inferred from his question  
that he didn't have a working solution, so I suggested the simplest  
working solution that was inline with his current mindset.  I didn't  
mean to imply it was the best solution, but my response was so short  
it easily could be read that way.  I assumed that if performance  
wasn't adequate, we would get a follow-up question.  But, I think it  
is better to start with an easy-to-understand working solution and  
then optimize it if necessary.


Regards,

Aaron


#import 

int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];

NSString *string1, *string2;

// create a string
	string1 = [[NSFileManager defaultManager]  
stringWithFileSystemRepresentation:argv[0] length:strlen(argv[0])];

NSLog(@"String value: %@", string1);
	NSLog(@"String 1 class: %@ address: %p retain count: %ld",  
NSStringFromClass([string1 class]), string1, [string1 retainCount]);

string2 = [string1 copy];
	NSLog(@"String 2 class: %@ address: %p retain count: %ld",  
NSStringFromClass([string2 class]), string2, [string2 retainCount]);


// create a path-optimized string
string1 = [string1 stringByDeletingLastPathComponent];
NSLog(@"String value: %@", string1);
	NSLog(@"String 1 class: %@ address: %p retain count: %ld",  
NSStringFromClass([string1 class]), string1, [string1 retainCount]);

string2 = [string1 copy];
	NSLog(@"String 2 class: %@ address: %p retain count: %ld",  
NSStringFromClass([string2 class]), string2, [string2 retainCount]);


[pool drain];
return 0;
}

Compile on the command line with:

$ gcc -framework Foundation -o test test.m

An example run:

$ /tmp/stringtest/test
2009-07-26 20:06:25.258 test[15385:903] String value: /tmp/stringtest/ 
test
2009-07-26 20:06:25.262 test[15385:903] String 1 class: NSCFString  
address: 0x10010c630 retain count: 1
2009-07-26 20:06:25.266 test[15385:903] String 2 class: NSCFString  
address: 0x10010c630 retain count: 2

2009-07-26 20:06:25.267 test[15385:903] String value: /tmp/stringtest
2009-07-26 20:06:25.267 test[15385:903] String 1 class: NSPathStore2  
address: 0x100110560 retain count: 1
2009-07-26 20:06:25.268 test[15385:903] String 2 class: NSPathStore2  
address: 0x100110560 retain count: 2





smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comment

Re: Display csv in a tableView with bindings

2009-07-26 Thread Adam R. Maxwell


On Jul 26, 2009, at 3:04 PM, Kyle Sluder wrote:

On Jul 26, 2009, at 2:52 PM, "Adam R. Maxwell"   
wrote:


"CFString objects perform other “tricks” to conserve memory, such  
as incrementing the reference count when a CFString is copied."


Not every NSString is necessarily a CFString. They're toll-free  
bridged, but that just means the CF implementation needs to be aware  
of any non-NSCFString instances it is handed. I belive the private  
NSPathStorage class might not be a subclass of NSCFString.


Correct.  The same design principle applies for NS classes, though,  
and a quick test program shows that -[NSPathStore2 copy] returns the  
same pointer.


IOW, just because two types are toll-free bridged does not mean they  
have the same behavior. Look at NSDictionary for a known example; if  
you create a CFDictionary with certain options and then use it as an  
NSDictionary you do not get the same behavior (I believe the  
relevant option involves whether the dictionary should copy its keys).


Yeah, that's part of it.  If you use pointer equality and  
copyWithZone: doesn't return the same object, setObject:forKey: will  
break your dictionary.


http://www.cocoabuilder.com/archive/message/cocoa/2006/6/9/165304



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant

On Jul 26, 2009, at 6:09 PM, Adam R. Maxwell wrote:

Can you go into a bit more detail with regard to the setting up the  
bindings? do I bind the tableView column to an arrayController  
which handles the rows? what model key path?


Personally, I recommend that you avoid bindings like the plague  
until you're comfortable with the datasource approach.


  Agreed. For my case, the datasource approach was much easier to  
manage and didn't take away from the app at all. It's only a *little*  
more code than with Bindings (since KVO timing issues required some  
extra custom logic in several instances for me) so the decision was an  
easy one.


--
I.S.




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant


On Jul 26, 2009, at 5:53 PM, gumbo...@mac.com wrote:


Thanks People, This is excellent advice and very helpful.

The main purpose of the app was to load the CSV (exported from  
Numbers) and turn the data into an HTML table with some hard coded  
CSS hooks. This works well now, but the format required from the CSV  
is not very flexible.


  Then NSDictionary will probably be fine for you. Performance test  
it and find out. Best test: a test file with many rows and few  
columns, then another with the same rows and many columns. Stick with  
nice round numbers and be consistent. The measure, measure, measure.


  Ultimately in this situation, as long as it "feels" reasonably  
fast, you're probably fine.




This is a very nice and tidy solution,


  You're damn right it is!

  Er, what I meant was, "I humbly thank you for your compliment." ;-)


I already have the tableView expanding to the size required to fit  
the data and the logic handles odd shaped tables. Can you go into a  
bit more detail with regard to the setting up the bindings? do I  
bind the tableView column to an arrayController which handles the  
rows? what model key path?


  Generally speaking, you'd dynamically create NSTableColumn  
instances as needed. For each column, you'd bind its value to the  
array controller's arrangedObjects.key where "key" represents the key  
for that column (the one that corresponds to the field in your row  
dictionary that the column represents).


  It's the same as in Interface Builder; you're just setting it up  
with code. See these two:


http://developer.apple.com/documentation/Cocoa/Reference/CocoaBindingsRef/BindingsText/NSTableColumn.html#//apple_ref/doc/uid/NSTableColumn-DontLinkElementID_601

http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Protocols/NSKeyValueBindingCreation_Protocol/Reference/Reference.html#//apple_ref/doc/uid/20002048-BCICHGHC


I imagine the largest table would be about 15x300, but I don't like  
making these assumptions, Murphy's law #1)
I am a little concerned about this, how much sleep should I be  
losing over this problem?


  For a first-pass, none at all. Go easy first, then optimize if  
necessary. Your users may not even notice. Given that Numbers itself  
is ... how shall we say ... unconcerned with performance ( :-) ), you  
can probably relax a bit yourself. In my situation (I actually have  
two separate ones with the same requirements), performance is  
everything and so is the ability to heavily reorganize and otherwise  
curate the data prior to using it.


  For me, it's worth losing some sleep over. YMMV.

--
I.S.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant

On Jul 26, 2009, at 6:05 PM, Adam R. Maxwell wrote:

Good point.  8--10 displayed in the table (typically), but each item  
has an arbitrary number of values (typically < 20, though).  Users  
can also display an arbitrary number of columns, so there are lots  
of fun performance problems to find :).




  The value of the column-mapper architecture I outlined increases  
with the number of columns. :-)


  I'm *still* finding new ways to make it even faster. Memory usage  
doesn't bother me as much as taking 40 seconds to scan through the  
rows looking for certain values to act upon (find/replace, convert,  
etc.). Sorting speed is about as fast either way, though.


--
I.S.




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread Adam R. Maxwell


On Jul 26, 2009, at 2:53 PM, gumbo...@mac.com wrote:
Can you go into a bit more detail with regard to the setting up the  
bindings? do I bind the tableView column to an arrayController which  
handles the rows? what model key path?


Personally, I recommend that you avoid bindings like the plague until  
you're comfortable with the datasource approach.




Unfortunately, I know from experience that when the row count gets  
above 8xx,000, NSTableView can no longer accurately draw rows in  
the view (if they are the standard-sized text fields).  But that is  
well beyond that magic tipping point :-)


I imagine the largest table would be about 15x300, but I don't like  
making these assumptions, Murphy's law #1)
I am a little concerned about this, how much sleep should I be  
losing over this problem?


15x300 is trivial.




smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Display csv in a tableView with bindings

2009-07-26 Thread Adam R. Maxwell


On Jul 26, 2009, at 2:58 PM, I. Savant wrote:

We have an application that keeps an array of bibliographic  
references, where each is an NSMutableDictionary with other  
properties.  The largest file I recall throwing at it is ~20K  
items, and the main problem at that point was a beachball when  
using SearchKit...which was a nuisance to work around.  It doesn't  
use bindings, but there really aren't any lazy loading tricks either.


 Well ... 20k items with only a couple of columns or 20k items with  
"many" columns. That one little detail makes all the difference. :-)


Good point.  8--10 displayed in the table (typically), but each item  
has an arbitrary number of values (typically < 20, though).  Users can  
also display an arbitrary number of columns, so there are lots of fun  
performance problems to find :).





smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Display csv in a tableView with bindings

2009-07-26 Thread Kyle Sluder

On Jul 26, 2009, at 2:52 PM, "Adam R. Maxwell"  wrote:

"CFString objects perform other “tricks” to conserve memory, such  
as incrementing the reference count when a CFString is copied."


Not every NSString is necessarily a CFString. They're toll-free  
bridged, but that just means the CF implementation needs to be aware  
of any non-NSCFString instances it is handed. I belive the private  
NSPathStorage class might not be a subclass of NSCFString.


IOW, just because two types are toll-free bridged does not mean they  
have the same behavior. Look at NSDictionary for a known example; if  
you create a CFDictionary with certain options and then use it as an  
NSDictionary you do not get the same behavior (I believe the relevant  
option involves whether the dictionary should copy its keys).


--Kyle Sluder



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant

On Jul 26, 2009, at 5:52 PM, Adam R. Maxwell wrote:

"CFString objects perform other “tricks” to conserve memory, such as  
incrementing the reference count when a CFString is copied."


http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFStrings/Articles/StringStorage.html#//apple_ref/doc/uid/20001179

  Exactly what I was looking for, thanks. I stand corrected and give  
Aaron back the "probably right" upgraded to a full "you're absolutely  
right". :-)




"Reasonably large files" is reasonably vague :).


  Quite. Back to the old "we don't know the OP's requirements".  
Because of this, vague (and covering as many caveats as possible) is  
the best answer.



We have an application that keeps an array of bibliographic  
references, where each is an NSMutableDictionary with other  
properties.  The largest file I recall throwing at it is ~20K items,  
and the main problem at that point was a beachball when using  
SearchKit...which was a nuisance to work around.  It doesn't use  
bindings, but there really aren't any lazy loading tricks either.


  Well ... 20k items with only a couple of columns or 20k items with  
"many" columns. That one little detail makes all the difference. :-)


--
I.S.





___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread gumboots

Thanks People, This is excellent advice and very helpful.

The main purpose of the app was to load the CSV (exported from  
Numbers) and turn the data into an HTML table with some hard coded CSS  
hooks. This works well now, but the format required from the CSV is  
not very flexible. So I thought if I could display the data, somehow,  
the user could sort as they required and select values to add css.


Well, you are correct that I assumed that it was a beginner question  
and that the OP was working with a fixed number of known columns (a  
reasonable assumption, I suppose, since he wants to use bindings).   
He could start with dictionaries, then switch to a custom class for  
rows if the performance using dictionaries was inadequate.


Definitely a beginner question, I still have to squint quite hard when  
it comes to the magic of bindings.


If you go the dictionary route, using the keys to identify the  
"fields" in each row, you're storing *way* more than just the  
individual field contents. You're storing a copy of your field  
identifier keys for every field, for every row. Best-case scenario,  
you're storing a pointer to some object that represents the  
"column" to which the fields belong, but this defeats the ease-of- 
use with bindings as you need string keys.


Not necessarily.  If the keys are NSStrings, then they are copied  
when added to the dictionary, but a copy of an immutable string is  
optimized to just retain it, so the data isn't duplicated (assuming  
all rows have the same columns in the same order, an assumption you  
don't seem to be making).


As I mentioned above, with increasingly large files, this  
dramatically increases your reading/writing time and uses a lot of  
memory. But at least you get the ability to easily use bindings and  
to sort, all for free, performance be damned.


Keep in mind that an NSArrayController created in Interface Builder  
is defined by default to create an NSMutableDictionary for each item  
in the dictionary.  It's not unreasonable, and we don't know the  
OP's performance requirements.


Performance just needs to be usable at this stage, once the concept is  
proven I can look further into this.




If you go another route (an array of arrays of strings), it's far  
more efficient, but adds a few programming complexities:


1 - How do you sort by a column? There's no key for sort  
descriptors and sorting via selector provides no way to pass  
additional information (such as column index or identifier).


2 - To what do you bind? The same limitation that causes concern in  
problem #1 makes #2 difficult ... and there is little by way of  
over-the-counter laxative to make #2 less difficult.


3 - If you intend to allow reordering of columns (built-in  
NSTableView feature) or even adding/removing columns, how do you  
handle keeping the columns mapped to the correct fields in the row  
array in the absence of an associative array (dictionary)?


The easiest solution to all three of these problems (in my opinion)  
is to make a "row" a custom class and a helper class (we'll call it  
"ColumnMapper" - one mapper shared among all rows). The row's  
internal storage can still be an array of strings for low overhead,  
but the Row class has a trick up its sleeve. It overrides - 
valueForUndefinedKey: so that it can still look up associative  
values (like a dictionary) but without storing them. The storage  
occurs once in the ColumnMapper.


This is a very nice and tidy solution, I already have the tableView  
expanding to the size required to fit the data and the logic handles  
odd shaped tables. Can you go into a bit more detail with regard to  
the setting up the bindings? do I bind the tableView column to an  
arrayController which handles the rows? what model key path?


Unfortunately, I know from experience that when the row count gets  
above 8xx,000, NSTableView can no longer accurately draw rows in the  
view (if they are the standard-sized text fields).  But that is well  
beyond that magic tipping point :-)


I imagine the largest table would be about 15x300, but I don't like  
making these assumptions, Murphy's law #1)
I am a little concerned about this, how much sleep should I be losing  
over this problem?

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread Adam R. Maxwell


On Jul 26, 2009, at 2:38 PM, I. Savant wrote:


On Jul 26, 2009, at 3:52 PM, Aaron Burghardt wrote:

Not necessarily.  If the keys are NSStrings, then they are copied  
when added to the dictionary, but a copy of an immutable string is  
optimized to just retain it, so the data isn't duplicated (assuming  
all rows have the same columns in the same order, an assumption you  
don't seem to be making).


 Actually, I temporarily take back my "you're probably right"  
response. :-) I can't find a reference to this anywhere, but I  
admittedly only looked in the NSString API reference, the  
Introduction to Strings Programming Guide for Core Foundation and  
quickly perused the The Objective-C 2.0 Programming Language.


 Would you mind directing me to where this is stated? I'm not saying  
you're wrong - it sounds plausible - I'm just not sure you're  
right. :-)


"CFString objects perform other “tricks” to conserve memory, such as  
incrementing the reference count when a CFString is copied."


http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFStrings/Articles/StringStorage.html#//apple_ref/doc/uid/20001179


It's not unreasonable, and we don't know the OP's performance  
requirements.




 No, it's not unreasonable, but since we don't know the OP's  
performance requirements, the original blanket statement that  
NSDictionary is better won't do without these caveats (ie, "it's  
easier for bindings, but dog-slow on reasonably large files").  
Rather than just say "there's more to it than that" as a drive-by  
correction, I wanted to provide a helpful explanation and  
workaround, since this is an area in which I have recent and  
detailed experience. :-)


"Reasonably large files" is reasonably vague :).  We have an  
application that keeps an array of bibliographic references, where  
each is an NSMutableDictionary with other properties.  The largest  
file I recall throwing at it is ~20K items, and the main problem at  
that point was a beachball when using SearchKit...which was a nuisance  
to work around.  It doesn't use bindings, but there really aren't any  
lazy loading tricks either.





smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant

On Jul 26, 2009, at 3:52 PM, Aaron Burghardt wrote:

Not necessarily.  If the keys are NSStrings, then they are copied  
when added to the dictionary, but a copy of an immutable string is  
optimized to just retain it, so the data isn't duplicated (assuming  
all rows have the same columns in the same order, an assumption you  
don't seem to be making).


  Actually, I temporarily take back my "you're probably right"  
response. :-) I can't find a reference to this anywhere, but I  
admittedly only looked in the NSString API reference, the Introduction  
to Strings Programming Guide for Core Foundation and quickly perused  
the The Objective-C 2.0 Programming Language.


  Would you mind directing me to where this is stated? I'm not saying  
you're wrong - it sounds plausible - I'm just not sure you're right. :-)



Keep in mind that an NSArrayController created in Interface Builder  
is defined by default to create an NSMutableDictionary for each item  
in the dictionary.


  I missed this the first time around, sorry.

  With respect, I don't see how this is relevant to my point. It only  
illustrates that NSMutableDictionary is an acceptable container (and  
it's the default for NSArrayController because it's *the* generic  
Cocoa container that fits in nicely with KVC). That it's the default  
says nothing about its performance when there are hundreds of  
thousands of them to create and manipulate.



It's not unreasonable, and we don't know the OP's performance  
requirements.




  No, it's not unreasonable, but since we don't know the OP's  
performance requirements, the original blanket statement that  
NSDictionary is better won't do without these caveats (ie, "it's  
easier for bindings, but dog-slow on reasonably large files"). Rather  
than just say "there's more to it than that" as a drive-by correction,  
I wanted to provide a helpful explanation and workaround, since this  
is an area in which I have recent and detailed experience. :-)


--
I.S.




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant
On Sunday, July 26, 2009, Aaron Burghardt  wrote:

> Not necessarily.  If the keys are NSStrings, then they are copied when added 
> to the dictionary, but a copy of an immutable string is optimized to just 
> retain it, so the data isn't duplicated (assuming all rows have the same 
> columns in the same order, an assumption you don't seem to be making).
>

  You're probably right about the strings ... but (continued below) ...

> A reasonable idea if the circumstances require it.  It would certainly avoid 
> storing a reference to each key in each row, so it would save a little 
> memory, but with the mapping of indexes to column names, it may not be any 
> faster than a dictionary.
>

  This I've tested. It (creation and manipulation) takes less than ten
percent of the time with this method than does the dictionary
approach. A dramatic difference as I said.


> Unfortunately, I know from experience that when the row count gets above 
> 8xx,000, NSTableView can no longer accurately draw rows in the view (if they 
> are the standard-sized text fields).  But that is well beyond that magic 
> tipping point :-)
>

  It certainly does.

--
I.S.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread Aaron Burghardt


On Jul 26, 2009, at 10:53 AM, I. Savant wrote:


On Jul 26, 2009, at 6:32 AM, Aaron Burghardt wrote:

Neither, you want an array of dictionaries where each row of CSV is  
a dictionary in which the values keyed to column names and each row  
of CSV is one dictionary object in the array.


 This is a bit more complicated than that, actually.

 There's a bit of a catch-22 here. On the one hand, you have a  
performance consideration. On the other, you have an ease-of- 
programming consideration. Using NSDictionary is easier, but for  
moderately-sized files it is noticeably slow, for large files, it's  
unusably so.


Well, you are correct that I assumed that it was a beginner question  
and that the OP was working with a fixed number of known columns (a  
reasonable assumption, I suppose, since he wants to use bindings).  He  
could start with dictionaries, then switch to a custom class for rows  
if the performance using dictionaries was inadequate.


 If you go the dictionary route, using the keys to identify the  
"fields" in each row, you're storing *way* more than just the  
individual field contents. You're storing a copy of your field  
identifier keys for every field, for every row. Best-case scenario,  
you're storing a pointer to some object that represents the "column"  
to which the fields belong, but this defeats the ease-of-use with  
bindings as you need string keys.


Not necessarily.  If the keys are NSStrings, then they are copied when  
added to the dictionary, but a copy of an immutable string is  
optimized to just retain it, so the data isn't duplicated (assuming  
all rows have the same columns in the same order, an assumption you  
don't seem to be making).


As I mentioned above, with increasingly large files, this  
dramatically increases your reading/writing time and uses a lot of  
memory. But at least you get the ability to easily use bindings and  
to sort, all for free, performance be damned.


Keep in mind that an NSArrayController created in Interface Builder is  
defined by default to create an NSMutableDictionary for each item in  
the dictionary.  It's not unreasonable, and we don't know the OP's  
performance requirements.


 If you go another route (an array of arrays of strings), it's far  
more efficient, but adds a few programming complexities:


1 - How do you sort by a column? There's no key for sort descriptors  
and sorting via selector provides no way to pass additional  
information (such as column index or identifier).


2 - To what do you bind? The same limitation that causes concern in  
problem #1 makes #2 difficult ... and there is little by way of over- 
the-counter laxative to make #2 less difficult.


3 - If you intend to allow reordering of columns (built-in  
NSTableView feature) or even adding/removing columns, how do you  
handle keeping the columns mapped to the correct fields in the row  
array in the absence of an associative array (dictionary)?


 The easiest solution to all three of these problems (in my opinion)  
is to make a "row" a custom class and a helper class (we'll call it  
"ColumnMapper" - one mapper shared among all rows). The row's  
internal storage can still be an array of strings for low overhead,  
but the Row class has a trick up its sleeve. It overrides - 
valueForUndefinedKey: so that it can still look up associative  
values (like a dictionary) but without storing them. The storage  
occurs once in the ColumnMapper.


A reasonable idea if the circumstances require it.  It would certainly  
avoid storing a reference to each key in each row, so it would save a  
little memory, but with the mapping of indexes to column names, it may  
not be any faster than a dictionary.




 Of course for very large files, both methods will be slow (and  
memory-intensive), and the problem becomes far more complex because  
then you need to start considering low-level solutions that don't  
ignore encodings. The anthesis to this concern is that, as the  
complexity and size increase, the likelihood that a human will want  
to see it as a table they will manually manipulate decreases (or at  
least, the reasonableness of the request does). At that magic  
tipping point, it's easy to argue that a GUI editor is no longer  
feasible and most of this problem goes away.


Unfortunately, I know from experience that when the row count gets  
above 8xx,000, NSTableView can no longer accurately draw rows in the  
view (if they are the standard-sized text fields).  But that is well  
beyond that magic tipping point :-)


Regards,

Aaron



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email s

Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant

On Jul 26, 2009, at 12:04 PM, Scott Andrew wrote:

If x number of objects in your CSV file represent an object, then  
parse it by hand and put the data into an object that it represents.


  This assumes your CSV will always represent a certain data type.  
That's a pretty big assumption for a data format that is purposefully  
wide open so that it can define a multitude of "record" formats.


  If you already know the structure, then it's a well-defined format  
and you're unlikely to be using CSV anyway. Of course, only the OP can  
answer this in his case.


--
I.S.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread Scott Andrew
If x number of objects in your CSV file represent an object, then  
parse it by hand and put the data into an object that it represents.   
For example:


Scott Andrew, 40, Computer Programmer

These might get parsed into a contact class that has properties name,  
age, profession. Then the bindings can be mapped to an array of  
contacts. This assumes that the values represent an object. Of course  
there are catch 22's that are mentioned else where in this thread.


Scott

On Jul 24, 2009, at 5:11 PM, gumbo...@mac.com wrote:


I need some direction please.

I would like to load a csv file and display the contents in an  
NSTableView. What is the best way to achieve this with bindings?


Should the model store the data in an array of arrays (rows and  
columns) or a dictionary of arrays (keyed columns and rows)?


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/scottandrew%40roadrunner.com

This email sent to scottand...@roadrunner.com


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Display csv in a tableView with bindings

2009-07-26 Thread I. Savant

On Jul 26, 2009, at 6:32 AM, Aaron Burghardt wrote:

Neither, you want an array of dictionaries where each row of CSV is  
a dictionary in which the values keyed to column names and each row  
of CSV is one dictionary object in the array.


  This is a bit more complicated than that, actually.

  There's a bit of a catch-22 here. On the one hand, you have a  
performance consideration. On the other, you have an ease-of- 
programming consideration. Using NSDictionary is easier, but for  
moderately-sized files it is noticeably slow, for large files, it's  
unusably so.


  If you go the dictionary route, using the keys to identify the  
"fields" in each row, you're storing *way* more than just the  
individual field contents. You're storing a copy of your field  
identifier keys for every field, for every row. Best-case scenario,  
you're storing a pointer to some object that represents the "column"  
to which the fields belong, but this defeats the ease-of-use with  
bindings as you need string keys. As I mentioned above, with  
increasingly large files, this dramatically increases your reading/ 
writing time and uses a lot of memory. But at least you get the  
ability to easily use bindings and to sort, all for free, performance  
be damned.


  If you go another route (an array of arrays of strings), it's far  
more efficient, but adds a few programming complexities:


1 - How do you sort by a column? There's no key for sort descriptors  
and sorting via selector provides no way to pass additional  
information (such as column index or identifier).


2 - To what do you bind? The same limitation that causes concern in  
problem #1 makes #2 difficult ... and there is little by way of over- 
the-counter laxative to make #2 less difficult.


3 - If you intend to allow reordering of columns (built-in NSTableView  
feature) or even adding/removing columns, how do you handle keeping  
the columns mapped to the correct fields in the row array in the  
absence of an associative array (dictionary)?


  The easiest solution to all three of these problems (in my opinion)  
is to make a "row" a custom class and a helper class (we'll call it  
"ColumnMapper" - one mapper shared among all rows). The row's internal  
storage can still be an array of strings for low overhead, but the Row  
class has a trick up its sleeve. It overrides -valueForUndefinedKey:  
so that it can still look up associative values (like a dictionary)  
but without storing them. The storage occurs once in the ColumnMapper.


  When asked for a field value for a column, a Row asks the  
ColumnMapper for the index (the index in its storage array) for the  
field the column represents. Likewise for storing a field value. This  
works because, since Row doesn't respond to these column ids as keys,  
it KVC falls back to -valueForUndefinedKey: and our Row class  
overrides this and relies on the central ColumnMapper to determine  
where in its internal storage the value for that column ID is located.


  This solves the sorting issue quite nicely too, if you sort using  
descriptors. Since NSSortDescriptor uses KVC, it "just works". Don't  
forget to google around for "Finder-like sorting" ... the built-in  
methods make a mess of alphanumeric strings. I leave implementing that  
to your imagination ... it's actually really easy if you spend a few  
minutes with Google.


  Note also this approach requires that all rows have the same number  
of columns/fields. Your parsing logic will have to account for this by  
either automatically adjusting (fraught with complexities and  
assumptions) or rejecting the file and informing the user of the first  
row where trouble begins - ie, the first row where the number of  
fields/columns differ from the rest. You really should take this route  
anyway, since the missing field in a row might be somewhere other than  
the end ... so what do you do with the remaining fields in the row?  
They are probably in the wrong column and there's no way to know  
because of CSV's inherent lack of solid structure.


  The only remaining problem is bindings. If you want to be able to  
handle any CSV file (ie, the "fields" are unknown), I'm afraid there's  
no way to use bindings in IB. You'll have to create the table columns  
(and bind them) in code once you've parsed your file and determined  
the number of columns. In this regard, you might find it just as easy  
(if not easier) to eschew Cocoa Bindings altogether and just use the  
NSTableDatasource protocol. It gives you more precise control over  
what to refresh and when. Trust me, this will come up.


  Of course for very large files, both methods will be slow (and  
memory-intensive), and the problem becomes far more complex because  
then you need to start considering low-level solutions that don't  
ignore encodings. The anthesis to this concern is that, as the  
complexity and size increase, the likelihood that a human will want to  
see it as a table they will

Re: Display csv in a tableView with bindings

2009-07-26 Thread Aaron Burghardt


On Jul 24, 2009, at 8:11 PM, gumbo...@mac.com wrote:


I need some direction please.

I would like to load a csv file and display the contents in an  
NSTableView. What is the best way to achieve this with bindings?


Should the model store the data in an array of arrays (rows and  
columns) or a dictionary of arrays (keyed columns and rows)?




Neither, you want an array of dictionaries where each row of CSV is a  
dictionary in which the values keyed to column names and each row of  
CSV is one dictionary object in the array.


Aaron



smime.p7s
Description: S/MIME cryptographic signature
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Display csv in a tableView with bindings

2009-07-24 Thread gumboots

I need some direction please.

I would like to load a csv file and display the contents in an  
NSTableView. What is the best way to achieve this with bindings?


Should the model store the data in an array of arrays (rows and  
columns) or a dictionary of arrays (keyed columns and rows)?


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com