Re: Best way to hook into the run loop?
Re: Best way to hook into the run loop?
- Subject: Re: Best way to hook into the run loop?
- From: Mike Abdullah <email@hidden>
- Date: Sun, 6 Dec 2009 11:57:17 +0000
On 6 Dec 2009, at 10:53, Graham Cox wrote:
>
> On 06/12/2009, at 8:12 PM, Uli Kusterer wrote:
>
>> I thought that was what undo groups were for? Open a group at the start of the drag manually, close it at the end, and everything in between gets lumped into one big action at the end. It may get "replayed" internally, but will all be triggered by one Cmd-Z.
>
>
> Indeed, undo groups are great. Unfortunately, NSUndoManager has a bug where if you open a group (on mouse down, say), do nothing (no drag), and close it again (on mouse up), an empty Undo task appears in the Undo menu. It's harmless, in that it does nothing, but it's also a nuisance, since the user doesn't expect this and reports it as a bug with your app.
But why are you opening a group without registering an undo action? Why not just wait until the first action actually needs to be registered?
> It's working around this bug that is horrible and surprisingly complicated (for two reasons - one, you can't peek at the top of the undo stack to see what's there and two, even if you could there's no way to tell whether the task there is empty, because the 'tasks' are all private classes. Therefore you have to come up with another way either to detect this case, or to prevent it from happening. Either way, it's a complicated and nasty hack). Incidentally I have reported this bug but it came back as a dupe. It's been there since I started with Cocoa, on 10.2.
I'm not even sure it is a bug, since the undo manager is designed to work in terms of groups, not individual actions.
>
> In addition, you don't really want a group to record every intermediate step of a drag - theoretically that could run to any number of tasks, which on Undo would be 'replayed', so the drag would eventually get undone but who cares about all the in-between steps? You just want the object to return to the position at the start of the drag. This is what 'task coalescing' achieves, along with the potentially huge memory saving of not recording the irrelevant in-between steps. Unfortunately NSUndoManager doesn't support task coalescing, so you have to subclass it to add this. It's not a huge deal but the bogus task problem is.
So again, why not just wait till the end of the drag and record a single action?
>
> I've now written my own undo manager from scratch. It's much more straightforward than NSUndoManager in that it uses Cocoa collection classes internally - I'm guessing that one reason for NSUndoManager's arcane implementation with all its weird group end and start markers and so on is so that it also works with Core Foundation alone. It turns out my approach is coincidentally very near identical to GNUStep's implementation. I was concerned that because it subclasses NSObject, not NSUndoManager, it would cause trouble when passed to NSDocument's -setUndoManager: method, but so far I can report that it works perfectly with no issues, supports coalescing and doesn't exhibit the empty group bug. It has an identical public API to NSUndoManager so my main concern was whether internal parts of Cocoa were using private API but that does not appear to be the case. I followed the documentation with respect to when the various notifications are sent, and that didn't quite keep NSDocument's dirty state properly in synch, so I did what was necessary to keep it happy and so now it's slightly not as documented - but I suspect the issue there is that the docs are subtly incorrect. There's also a suspicion among users who contacted me off-list that Core Data is doing something with private Undo API, so mine may not support a Core Data app, but for now that doesn't concern me.
>
> I've still got some testing to do to really prove it's safe to use, but so far I'm much happier with it than NSUndoManager (and if things do go wrong I can at least debug it directly instead of having to guess what's going on inside the black box and relying on the inaccurate documentation). I'll put it out on my website when I'm done - not seeing those useless 'undo manager is in an invalid state' logs is liberating, I can tell you.
>
> --Graham
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> 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:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden