• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSKeyedArchiver - better ways to autosave documents?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSKeyedArchiver - better ways to autosave documents?


  • Subject: Re: NSKeyedArchiver - better ways to autosave documents?
  • From: Guy English <email@hidden>
  • Date: Thu, 1 Sep 2005 20:10:06 -0400

Hi Keith,

You bring up a good point about the renaming and rearranging of nodes. Basically what you want to do is track all the user actions that change that project part of your model. You can think of it a lot like an undo manager - when you replay the journal you're at the very bottom of the undo stack and you redo each action until you've emptied the stack. So, yes, you play back in the order the actions occurred. Each node having a unique id is great - it's going to make things easier. Here's what I suggest and note that I haven't implemented this for a Cocoa so it's more of a conceptual level suggestion so the Real World may get in the way a little.

Create a class as the Journal Manager. When you create a node you will register it with the Journal Manager. The Journal Manager will add a 'create' action which will store the initial state of your node. I suggest capturing the node state using the archive method you've already got. It's good to do it this way because if you replay an old journal that just says 'create' and you've changed the defaults for an object since the journal was created you'll run into discrepancy problems. This may happen if a user is working, your app dies but has autosaved, the user downloads the new non-crashing version of your app and loads up the project he was working on. The new non-crashing version has different defaults for the node object and things go south again. Unhappy user. Best to stash the state you know the journal is working from. When a node is deleted you deregister it from the Journal Manager which stores a 'delete' action for the given node id.

Great, but what about the state changes in-between creation and deletion? Here's where the magic happens. When you register a node with the Journal Manager it uses Key Value Observing to observe the node. You will be called each time a KVO setter is used on the node. Simply append to the journal a 'set' action for the node id with the key and new value. You're done. You can now track a nodes state from creation to deletion.

    Replaying follows this code-ish looking thing:

unsigned i, max;
max = [actions count];
for ( i = 0; i < max; i++ )
{
NSDictionary *action = [actions objectAtIndex: i];
switch ( [[action objectForKey: @"ActionType"] intValue] )
{
case MyActionCreate:
[self createNewNodeFromNodeState: [action objectForKey: @"InitalNodeState"]];
break;


case MyActionDelete:
MyNode *node = [self nodeWithUniqueID: [action objectForKey: @"uuid"]];
[self removeNode: node];
break;


case MyActionSetValue:
MyNode *node = [self nodeWithUniqueID: [action objectForKey: @"uuid"]];
[node setValue: [action objectForKey: @"value"] forKey: @"key"];
break;


         default:
             // panic!
             break;
    }
}

Now ... here's where Real Life gets to be an ass about things. First ... you're using KVC compliant methods, right? If you're not you'll need to do things the hard way. Second ... you need to know what keys on the node to observe. There are a few routes to this. You can use NSObjects +exposeBinding in the node class to advertise the bindings and -exposedBindings in the Journal Manager to work out which keys to observe. Or you can make your own method which the Journal Manager will call that will return an array of keys to observe. Both of these methods require a bit of maintenance - each time you add a property you need to expose it to the Journal Manager. Certainly it's less maintenance than doing things without KVO and it's not very error prone ( just append a string to an array ) but it's code you need to remember to write. Alternatively you can try to guess all the KVO keys a class supports by poking around the runtime. I've got a category on NSObject that'll do that but ... well, I'm not sure it's such a good idea. You'll end up logging changes to keys you may not want to.

Anyway, from there I think you've got a good shot at getting a decent implementation. Tricky points include that the *parent* node will get the 'set' action when a child is repositioned in it's list and remembering that by using Key Value Coding in the journal file you expose object APIs to the file format. Remove an accessor or ivar and be prepared to deal with it in the Journal Manager. Before applying a set action make sure the key is one you allow the journal to be setting for instance.

Hope that helps,
Guy
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: NSKeyedArchiver - better ways to autosave documents?
      • From: Keith Blount <email@hidden>
  • Prev by Date: NSString initWithBytes
  • Next by Date: Crash when autorelease pool cycles - how to tell what object is causing the problem?
  • Previous by thread: Re: NSString initWithBytes
  • Next by thread: Re: NSKeyedArchiver - better ways to autosave documents?
  • Index(es):
    • Date
    • Thread