• 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: Keith Blount <email@hidden>
  • Date: Tue, 6 Sep 2005 13:31:45 -0700 (PDT)

Hello Guy,

I am sorry for not replying to this earlier - it's
been a busy week. I just wanted to say many thanks for
taking the time to help and for your excellent
suggestions. I have decided that I am going to go
ahead and implement something like your journalling
suggestion, as this does seem the best solution. Given
that there are only a few points at which I will ever
need to record changes (additions, renaming etc),
rather than take the KVO route (which could get messy
even though my methods are KVO-compliant) I will
probably use the undo manager analogy and just have a
-registerChange: method or some such for my journal
manager.

Given that this is potentially a complicated job,
though, I have moved it down my "to do" list for my
app and will start hashing it out once the main
functionality is finished (in a few weeks hopefully).

It is a shame that there isn't already a faster
alternative to NSKeyedArchiver in place for saving
large arrays and dictionaries, given that it is a
problem that comes up a lot.

Many thanks again,
Keith

--- Guy English <email@hidden> wrote:

> 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
>





______________________________________________________
Click here to donate to the Hurricane Katrina relief effort.
http://store.yahoo.com/redcross-donate3/
 _______________________________________________
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

References: 
 >Re: NSKeyedArchiver - better ways to autosave documents? (From: Guy English <email@hidden>)

  • Prev by Date: Re: [cocoa scripting] getting script class attribute name
  • Next by Date: Strange bug (?) with NSArrayController sortDescriptors and SQLite !
  • Previous by thread: Re: NSKeyedArchiver - better ways to autosave documents?
  • Next by thread: Crash when autorelease pool cycles - how to tell what object is causing the problem?
  • Index(es):
    • Date
    • Thread