PDA

View Full Version : Cocoa TableView Binding w/ NSMutableArray of NSNetService - Assistance Requested




justindz
Jan 16, 2006, 08:10 AM
I have an NSDrawer containing an NSTableView. In my application, I have an NSMutableArray populated with NSNetService objects picked up by my NSNetServiceBrowser. I want to bind the NSTableView to the contents of the array so that it displays the computer names discovered. This is for a game client's player list. I have verified that the browser accurately detects and stores the service entries but cannot--despite much wailing and gnashing of teeth--get the table to display any data. I don't have any errors or related warnings, though.

I believe that I am missing either 1) a small detail or 2) a big, ethereal truth about Bindings. I've read pages and pages of online materials and tutorials and have adjusted by NIB and code several times according to instructions and reports of success. There seems to be a lot of frustration in this area--it would be nice if Apple put up a more comprehensive tutorial. It seems as if all the tutorials are incomplete in some way.

Attached is a zip file of my project directory. I really appreciate any help--I've put several days into this with no progress. I started with a delegate/datasource approach to the table, got no where with that, switched to bindings and go no where with that. I'm frustrated enough to ditch my project and do something non-Mac native for the networking and GUI.



caveman_uk
Jan 16, 2006, 08:36 AM
I can't check your code just now as I'm on windows. One thing I will say is that in my general experience I've found that bindings are great if you do what Apple expects you to do. Try anything a bit different and you end up in a world of pain. Often it's just easier to write the damn datasource methods like you always did.

One thing to be aware of is that you must make changes to your source array so that the bindings system is aware that you've done it. What may be happening is that the bindings are working but only see the empty array before you added the items to it. Check out this...

In some situations you may find that programmatic modifications to arrays pass unnoticed by a table view. You should not modify the contents of an object "behind the controller's back" (unless you want to make a large number of changes in a single operation, and handle the observer notification yourself -- see below ("Batch import into an array, and other mass changes").

You can safely modify a bound-to to-many relationship by:

* Using KVC, unless automatic KVO notification is turned off for the relationship. If you invoke -mutableArrayValueForKey: and mutate the returned array in any way, appropriate KVO notifications are sent.
* Using KVO-compliant methods (see below), unless automatic KVO notification is turned off for the relationship. If you invoke any of the modification methods, appropriate notifications are sent.
* Doing virtually anything you want, as long as the modification is accompanied by manual KVO notification. Properly paired invocations of -willChangeValueForKey:/-didChangeValueForKey: and -willChange:valuesAtIndexes:forKey:/-didChange:valuesAtIndexes:forKey: always cause all observers of the relevant key to be notified.

KVO-compliant accessor methods for to-many relationships are detailed here: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/AccessorConventions.html. The general form of the methods is summarised below:

* - (unsigned int)countOfKey;
* - (id)objectInKeyAtIndex:(unsigned int)index;
* - (void)insertObject:(id)anObject inKeyAtIndex:(unsigned int)index;
* - (void)removeObjectFromKeyAtIndex:(unsigned int)index;
* - (void)replaceObjectInKeyAtIndex:withObject: (This is optional, but provides performance enhancements, and may be required if you make any modifications to objects in insertObject: inKeyAtIndex: that you want to avoid in a replacement.)


This is from this page (http://homepage.mac.com/mmalc/CocoaExamples/controllers.html) which is one of the best resources on bindings. Again, I haven't looked at your code but this has bitten me a couple of times. It's because your nib is often loaded (and the contents of the tableview) before you've actually set up your array.

robbieduncan
Jan 16, 2006, 09:13 AM
I can't check your code just now as I'm on windows. One thing I will say is that in my general experience I've found that bindings are great if you do what Apple expects you to do. Try anything a bit different and you end up in a world of pain. Often it's just easier to write the damn datasource methods like you always did.

I'm on Windows at the moment as well so can't check it out either. My initial thought would be that NSTableView does not know how to display a NSNetService. Try some sort of value transformer or create an array of NSStrings that are the name of the services?