Re: Best data source for table view in document window
On 07/09/2012, at 4:36 AM, Jerry Krinock wrote: > But I'm still using my other triggers because sometimes my document opens > with no windows Don't forget also that Cocoa will be creating instances of your document at all sorts of odd times with Autosave and Versions in play. This can play havoc with complex connections between elements of your app and throw up all sorts of weird bugs. Extensive testing is needed to catch all of these (and one reason I found using windowWillClose: was best for much of my tear-down in my case, because I skip the set-up associated with windows if there aren't any). --Graham ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On 2012 Sep 05, at 21:13, Martin Hewitson wrote: > I already had a -cleanUp method being called from -windowWillClose: within > the NSDocument I just checked my code again and found that I am already using -windowWillClose: as suggested by Graham, for the stuff in the window, and a quick test shows that -windowWillClose: is invoked earlier than my other triggers. But I'm still using my other triggers because sometimes my document opens with no windows, and there may be other programmatic ways that closing can be initiated. > (NSPersistentDocument, actually) Oh, that's even more fun! But apparently not related to the crash you're reporting. > I have in the back of my mind a memory about timers retaining their target, > but I think I handle that in the accepted way by calling -invalidate on the > timer. Yes, it looks OK to me. > > Maybe I shouldn't care about the order in which my dealloc messages appear? Yes, because you've already removed all vulnerable references in -windowWillClose: > With this new scheme described above, I've been able to open and close a > document many 10's of times without a crash. But somehow I have a nagging > doubt that I've really nailed this down. Use the software equivalent of Accelerated Life Testing. If your app is scriptable, write a script to open, stress, and close a document, and let it loop for several days. If not scriptable, either make it scriptable (which may have unforeseen future re-use), or patch in a temporary bonehead loop. ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
Thanks for the advice, gentlemen. I already had a -cleanUp method being called from -windowWillClose: within the NSDocument (NSPersistentDocument, actually), so I looked more carefully at how that particular view controller is torn down. I made some changes such that now, in the document's cleanUp, I call -tearDown on the view controller. It in turn calls -tearDown on its builder object (which uses a timer to repeatedly refresh the model objects). Currently I can't get the view controller and builder to dealloc before the document, which results in crashes: 2012-09-06 05:41:19.889 TeXnicle[2122:303] Dealloc 2012-09-06 05:41:19.902 TeXnicle[2122:303] Dealloc 2012-09-06 05:41:19.902 TeXnicle[2122:303] Dealloc Seems I'm doing something wrong. So, to recap, in the NSDocument I do: - (void)windowWillClose:(NSNotification *)notification { [self cleanUp]; } - (void) cleanUp { NSLog(@"Clean up..."); // outline view controller [self.outlineViewController tearDown]; self.outlineViewController = nil; // and lots of other stuff } then in the view controller I do: - (void) tearDown { NSLog(@"Outline view controller tearDown"); [self.view removeFromSuperview]; self.delegate = nil; self.outlineView.delegate = nil; self.outlineView.dataSource = nil; [self.outlineBuilder tearDown]; self.outlineBuilder = nil; } and in the builder I do - (void) tearDown { [self stopObserving]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [self stopTimer]; self.delegate = nil; dispatch_release(queue); } - (void) stopTimer { if (self.timer) { [self.sections removeAllObjects]; [self.timer invalidate]; self.timer = nil; } } I wonder if I'm coming a cropper because of the timer. I have in the back of my mind a memory about timers retaining their target, but I think I handle that in the accepted way by calling -invalidate on the timer. Maybe I shouldn't care about the order in which my dealloc messages appear? With this new scheme described above, I've been able to open and close a document many 10's of times without a crash. But somehow I have a nagging doubt that I've really nailed this down. Any further advice is greatly appreciated. I've spent a few weeks on and off trying to fix this particular class of crash, and I don't feel I'm much closer to the solution. Best wishes, Martin On 6, Sep, 2012, at 03:01 AM, Graham Cox wrote: > > On 06/09/2012, at 10:44 AM, Jerry Krinock wrote: > >> Regarding the indication, I've yet to find a single hook in Cocoa which >> gives me a reliable early warning that a document is closing. > > > If your document only has a single window, you could use: > > - (void) windowWillClose:(NSNotification*) notification; > > I've found this a reliable place (in fact the ONLY reliable place) to perform > tear-down of KVO, etc. Of course if you support multiple windows of the same > document that might need a bit of care to make work. > > > --Graham > ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On 06/09/2012, at 10:44 AM, Jerry Krinock wrote: > Regarding the indication, I've yet to find a single hook in Cocoa which gives > me a reliable early warning that a document is closing. If your document only has a single window, you could use: - (void) windowWillClose:(NSNotification*) notification; I've found this a reliable place (in fact the ONLY reliable place) to perform tear-down of KVO, etc. Of course if you support multiple windows of the same document that might need a bit of care to make work. --Graham ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
I'm still digesting all the fine advice in this thread. But since it seems like I'm going to keep my standalone data source in some form, here is a quick answer to Martin's question regarding crashes. On 2012 Sep 05, at 10:16, Martin Hewitson wrote: > occasional crashes that occur when the parent NSDocument instance (which has > an instance of the view controller and adds the view to the main window) is > closed. I believe I'm hitting corner cases where the outline view still tries > to display the objects which have already been released as a result of > closing the window. Yes. > Is there any advice as to how to handle these corner cases? Would it be > better (or for that matter, any different) to dispense with the stand-alone > 'builder' object and just compute the objects within the view controller? I don't think it would be any different, assuming that your adjunct 'builder' object is alive until the view controller deallocs. As far as the corner cases, I think Chris Hanson implied that an NSArrayController has the document-closing housekeeping built in. Interesting, but my NSTableView is actually an NSOutlineView, and NSTreeController would be too much of a rewrite. With the standalone data source, my approach is to set all relevant references to nil as soon as you get any indication that a document is closing. The references you want to nil are, of course, the table view's data source and delegate. But look both ways; also set the 'document' to nil in the standalone data source. Regarding the indication, I've yet to find a single hook in Cocoa which gives me a reliable early warning that a document is closing. So I've implemented a 'tearDown' method, with an interlock so that it only runs once, and fire at it liberally from multiple detectors… • Override -[NSDocumentController removeDocument:] • Override -[NSDocument close] • Override -[NSDocument readFromURL:ofType:error:], fire if anything fails • Fire early from any of your methods which cause a document to close ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On Sep 5, 2012, at 11:24 AM, Kyle Sluder wrote: > On Sep 5, 2012, at 5:39 AM, Jerry Krinock wrote: > >> What is the best the data source for a table view in a document window? The >> candidates are… >> >> (1) Category of the document. This is the way it is done in the >> WithoutBindings ("With and Without Bindings") Apple sample code. But it >> seems like too much "view-ish" code in the data model, particularly when my >> document class is also used in a GUI-less command-line tool, which has no >> need for this code. > > NSDocument is really a controller. Yup, and a data source is by nature a controller object: it mediates between a view (see the first argument to each data source method) and a model. Your document, your window controller, or a view controller would all be good candidates to be data sources. >> (4) Category of the table view itself, assuming that it is subclassed. >> Seems like a logical division. No worrying about whether table view or its >> data source gets deallocced first. Access the document via [[[self window] >> windowController] document]. > > Absolutely, completely, 100% not. Never ever do this. If NSTableView > privately implements any methods that it also expects the data source to > implement, you will get bad behavior. Not only that, you'd be putting controller-ish stuff (and, by necessity, model-ish stuff) into the view. The point of a data source is like the point of a delegate: so you can customize an object's behavior without having to subclass and without violating MVC. --Andy ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On Sep 5, 2012, at 11:53 AM, Seth Willits wrote: > In a complex window where there a multiple tabbed views like you have, think > of the window controller as doing nothing more than managing the view > controllers for each of the tabs, not the actual views in each tab. If your > window controller is getting monolithic, it's time for a refactor. Amen to that: You can really start to encapsulate portions of your view well this way, and the way they interact with your model as well. > There's a view controller responsible for doing nothing more than managing > the table view displaying the query results table, and basically has this > interface: > > @interface ResultListViewController : NSViewController { > NSTableView * resultListTableView; > NSArrayController * resultListArrayController; > } > > @property (readwrite, retain) NSArray * results; > > @end > > The view controller is the delegate and data source for the table view and > manages a bunch of little things related to the table. To go into a little more detail, I’d write the above like this, using Xcode 4.4 or later: In CMHResultListViewController.h: #import “CMHViewController.h” @interface CMHResultListViewController : CMHViewController @property (readwrite, copy) NSArray *results; - (id)init; // designated initializer @end In CMHResultListViewController.m: #import “CMHResultListViewController.h” // Class extension for UI, it's not part of this class’s API. @interface CMHResultListViewController () @property (readwrite, assign) IBOutlet NSTableView *resultListTableView; @property (readwrite, assign) IBOutlet NSArrayController *resultListArrayController; @end @implementation CMHResultListViewController { @private // …additional ivars that may be needed… } // …rest of implementation… @end With this, I would: - Use a “base subclass” of NSViewController for my project, in which I can implement project-wide functionality. (For example, I could make -init the designated initializer for such controllers, and have them derive their nib name from their class name.) - Separate things needed by Interface Builder (IBOutlet, delegate & data source protocol declarations) from the API of the class as used by the rest of the class. - Avoid declaring ivars that I don’t need to any more, since they’ll be auto-synthesized for me. - Avoid declaring ivars in the interface to the class, giving clients of it details that they should actively avoid caring about. - Make Interface Builder go through accessors (by putting the IBOutlet marker on the property declarations) rather than straight to ivars, allowing a little more flexibility. Of course, this all assumes using the latest tools and compiler, and no requirement to remain compatible with 32-bit Intel (the old ObjC runtime). If it had to remain compatible, though, about the only thing I’d have to do differently is put ivar declarations in the main @interface in the header file. -- Chris ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On Sep 5, 2012, at 5:39 AM, Jerry Krinock wrote: > (2) Separate, standalone object. Fancy housekeeping is needed to avoid > retain cycles, and crashes in corner cases as the document window is closing. This is the way to go. That housekeeping doesn’t need to be so fancy; you just need to establish who owns what, and tear everything down in a deterministic fashion. This kind of standalone object is pretty much exactly what NSArrayController is; before bindings[1], developers created analogous reusable classes themselves, using things like NSTableColumn’s “identifier” property to store a model key path to use. If you have the option, I’d recommend just using NSArrayController for this. It does a lot of what you’ll need already, and you can still also implement a table view delegate and data source (possibly in your own subclass of NSArrayController) for additional behavior that you may need. I’d also recommend breaking out ownership of your document’s view side into its own NSWindowController sooner rather than later. While NSDocument will create a generic window controller for you automatically, it provides a good separation of concerns to have a custom NSWindowController subclass own the rest of your view, and to have the document concern itself solely with “document-like” things such as persistence. -- Chris [1] Those who used the Enterprise Objects Framework used a combination of EODisplayGroup and EOAssociation for this. EODisplayGroup was much more like NSFetchedResultsController in Cocoa Touch than NSArrayController in Cocoa, however. ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On Sep 5, 2012, at 5:39 AM, Jerry Krinock wrote: > … except that my window controller for this multi-tabbed window is already > huge. In a complex window where there a multiple tabbed views like you have, think of the window controller as doing nothing more than managing the view controllers for each of the tabs, not the actual views in each tab. If your window controller is getting monolithic, it's time for a refactor. For example: http://araelium.com/querious/screenshots/query_75p.png (Ignoring the affects of having literal tabs in this window…) Each view up in the toolbar is a separate view controller, which is possibly composed of one or more child view controllers. In this particular screenshot, you're looking at four. The window controller has a piddly 600 lines of code in it which is merely for creating and swapping out views of the top level view controllers, etc. The real work is all done in a tree of view controllers. There's a view controller responsible for doing nothing more than managing the table view displaying the query results table, and basically has this interface: @interface ResultListViewController : NSViewController { NSTableView * resultListTableView; NSArrayController * resultListArrayController; } @property (readwrite, retain) NSArray * results; @end The view controller is the delegate and data source for the table view and manages a bunch of little things related to the table. -- Seth Willits ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
> > > >> >> (2) Separate, standalone object. Fancy housekeeping is needed to avoid >> retain cycles, and crashes in corner cases as the document window is closing. > > Quite common. This kind of life cycle management is part of living with Cocoa. > > Consider making this object an NSViewController subclass. > This is a very interesting thread for me. I have a similar case. I have a view controller which acts as a data source for an outline view. I have another class which builds the model objects that are to be viewed in the outline view. The view controller has an instance of this 'builder' class, and as such presents the objects the builder class creates in the outline view. Mostly it all works fine, but I have occasional crashes that occur when the parent NSDocument instance (which has an instance of the view controller and adds the view to the main window) is closed. I believe I'm hitting corner cases where the outline view still tries to display the objects which have already been released as a result of closing the window. I'm using ARC, and this presents itself as a retain call to objects which have already got a retain count of 0, and this happens in one of the outline view's data source methods. I'm being quite vague here because I'm having a great deal of difficulty debugging this and reproducing anything with any certainty. The reason I chose a stand-alone object was just to separate out that piece of code which gathers the model objects (by parsing some text) on a dispatch queue, from the code that does the displaying. Is there any advice as to how to handle these corner cases? Would it be better (or for that matter, any different) to dispense with the stand-alone 'builder' object and just compute the objects within the view controller? Best wishes, Martin 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
On Sep 5, 2012, at 5:39 AM, Jerry Krinock wrote: > What is the best the data source for a table view in a document window? The > candidates are… > > (1) Category of the document. This is the way it is done in the > WithoutBindings ("With and Without Bindings") Apple sample code. But it > seems like too much "view-ish" code in the data model, particularly when my > document class is also used in a GUI-less command-line tool, which has no > need for this code. NSDocument is really a controller. But if you already have a window controller subclass, then putting UI things in the document is kind of unnecessary. > > (2) Separate, standalone object. Fancy housekeeping is needed to avoid > retain cycles, and crashes in corner cases as the document window is closing. Quite common. This kind of life cycle management is part of living with Cocoa. Consider making this object an NSViewController subclass. > > (3) Category of the window controller. Probably not a bad choice, except > that my window controller for this multi-tabbed window is already huge. I start here and then move to #2 if the window controller gets too big. > > (4) Category of the table view itself, assuming that it is subclassed. > Seems like a logical division. No worrying about whether table view or its > data source gets deallocced first. Access the document via [[[self window] > windowController] document]. Absolutely, completely, 100% not. Never ever do this. If NSTableView privately implements any methods that it also expects the data source to implement, you will get bad behavior. This happened to someone using UITableView on this list a few years ago. Plus using window] windowController] document] is a terrible design. --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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
If the table view's data is related to the document, you should keep this in the document. Putting it in a category when the class is fully under your control seems a bit odd, but you may have a reason for that. You should look at your reservations, though. You're wanting to hook up a "data source" and you're feeling it's too much "view-ish" code for your "data model." Your "view-ish" code may be saying your design needs changing. Consider transformers or formatters if appropriate. Also, view-based tables and collection views open things up to more richer representations that may not require your "view-ish" code. Your separate, standalone object may be a good solution, too, but think of the has-a, is-a, or uses relationship between your document class and it, and that might help you know who owns your data. -- Gary L. Wade http://www.garywade.com/ On 9/5/2012 5:39 AM, "Jerry Krinock" wrote: >What is the best the data source for a table view in a document window? >The >candidates are? > >(1) Category of the document. This is the way it is done >in the WithoutBindings ("With and Without Bindings") Apple sample code. >But >it seems like too much "view-ish" code in the data model, particularly >when >my document class is also used in a GUI-less command-line tool, which has >no >need for this code. > >(2) Separate, standalone object. Fancy housekeeping >is needed to avoid retain cycles, and crashes in corner cases as the >document window is closing. > >(3) Category of the window controller. >Probably not a bad choice, except that my window controller for this >multi-tabbed window is already huge. > >(4) Category of the table view >itself, assuming that it is subclassed. Seems like a logical division. >No >worrying about whether table view or its data source gets deallocced >first. >Access the document via [[[self window] windowController] document]. > >* * >* > >I've used (2) but think I'm going to switch to (4). Any important >considerations I've >overlooked? > >Thanks, > >Jerry ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Best data source for table view in document window
I use a standalone singleton object in Matt Galloway style. Never ran into the crash you're mentioning. On Sep 5, 2012, at 8:39 AM, Jerry Krinock wrote: > What is the best the data source for a table view in a document window? The > candidates are… > > (1) Category of the document. This is the way it is done in the > WithoutBindings ("With and Without Bindings") Apple sample code. But it > seems like too much "view-ish" code in the data model, particularly when my > document class is also used in a GUI-less command-line tool, which has no > need for this code. > > (2) Separate, standalone object. Fancy housekeeping is needed to avoid > retain cycles, and crashes in corner cases as the document window is closing. > > (3) Category of the window controller. Probably not a bad choice, except > that my window controller for this multi-tabbed window is already huge. > > (4) Category of the table view itself, assuming that it is subclassed. > Seems like a logical division. No worrying about whether table view or its > data source gets deallocced first. Access the document via [[[self window] > windowController] document]. > > * * * > > I've used (2) but think I'm going to switch to (4). Any important > considerations I've overlooked? > > Thanks, > > Jerry > > > ___ > > 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: > https://lists.apple.com/mailman/options/cocoa-dev/zav%40mac.com > > This email sent to z...@mac.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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Best data source for table view in document window
What is the best the data source for a table view in a document window? The candidates are… (1) Category of the document. This is the way it is done in the WithoutBindings ("With and Without Bindings") Apple sample code. But it seems like too much "view-ish" code in the data model, particularly when my document class is also used in a GUI-less command-line tool, which has no need for this code. (2) Separate, standalone object. Fancy housekeeping is needed to avoid retain cycles, and crashes in corner cases as the document window is closing. (3) Category of the window controller. Probably not a bad choice, except that my window controller for this multi-tabbed window is already huge. (4) Category of the table view itself, assuming that it is subclassed. Seems like a logical division. No worrying about whether table view or its data source gets deallocced first. Access the document via [[[self window] windowController] document]. * * * I've used (2) but think I'm going to switch to (4). Any important considerations I've overlooked? Thanks, Jerry ___ 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com