Core Data and Document Packages

  • Aloha,

    I'm taking the plunge and switching a fair chunk of code to using
    Core Data instead of my own management of an SQLite database. At
    least that's the current plan. ;)

    My document-based app has a document type which uses a package
    instead of just a single file to store data in, because there is a
    need to store related files inside the package as well. Currently I'm
    doing some relatively simple overloading of standard NSDocument
    methods to open and save the database by using a path based off of
    the -fileName.

    With NSPersistentDocument, by default it uses the document's -
    fileName as the path for the persistent store. What is the best way
    to retarget it so that it uses a different path within the package? I
    imagine someone here must have done it, so I'm hoping to not have to
    fiddle for so long to figure it out, however it seems that I might
    simply be able to override
    configurePersistentStoreCoordinatorForURL:ofType:error: and pass a
    different URL to super's implementation? Will there be any side
    effects to this?

    Thanks. Total Core Data newb,

    --
    Seth Willits
  • On Jul 3, 2007, at 1:38 AM, Seth Willits wrote:

    > With NSPersistentDocument, by default it uses the document's -
    > fileName as the path for the persistent store. What is the best way
    > to retarget it so that it uses a different path within the package?
    > I imagine someone here must have done it, so I'm hoping to not have
    > to fiddle for so long to figure it out, however it seems that I
    > might simply be able to override
    > configurePersistentStoreCoordinatorForURL:ofType:error: and pass a
    > different URL to super's implementation? Will there be any side
    > effects to this?

    <http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Cla
    sses/NSPersistentDocument_Class/Reference/Reference.html
    >

    mmalc
  • On Jul 3, 2007, at 5:57 AM, mmalc Crawford wrote:

    >> With NSPersistentDocument, by default it uses the document's -
    >> fileName as the path for the persistent store. What is the best
    >> way to retarget it so that it uses a different path within the
    >> package? I imagine someone here must have done it, so I'm hoping
    >> to not have to fiddle for so long to figure it out, however it
    >> seems that I might simply be able to override
    >> configurePersistentStoreCoordinatorForURL:ofType:error: and pass a
    >> different URL to super's implementation? Will there be any side
    >> effects to this?
    >
    > <http://developer.apple.com/documentation/Cocoa/Reference/
    > ApplicationKit/Classes/NSPersistentDocument_Class/Reference/
    > Reference.html>
    >
    > mmalc

    I'm not sure how that was supposed to be helpful given that I had
    already read the documentation (not to mention the tutorials, sample
    code, Google, and the list archives) and came here asking for further
    help.

    As it turns out, overriding readFromURL:/writeToURL: and
    configurePersistentStoreCoordinatorForURL: is working dandily so far.
    In my previous experience doing this without Core Data, I had ran
    into some trouble with getting this to work, but the circumstances
    are different so it's a bit simpler and more direct than I was
    expecting it to be.

    For posterity, incomplete but demonstrable code of how to do it:

    - (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:
    (NSString *)fileType error:(NSError **)error;
    {
        NSString * storePath = [[url relativePath]
    stringByAppendingPathComponent:@"Data.sqldb"];
        return [super configurePersistentStoreCoordinatorForURL:[NSURL
    fileURLWithPath:storePath] ofType:fileType error:error];
    }

    - (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
    error:(NSError **)error;
    {
        NSString * packagePath = [absoluteURL relativePath];
        BOOL isDirectory = NO;

        if (![[NSFileManager defaultManager]
    fileExistsAtPath:packagePath isDirectory:&isDirectory] || !
    isDirectory) {
            // create an error
            return NO;
        }

        return [super readFromURL:absoluteURL ofType:typeName error:error];
    }

    - (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
    forSaveOperation:(NSSaveOperationType)saveOperation
    originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:
    (NSError **)error;
    {
        NSString * packagePath = [absoluteURL relativePath];
        BOOL isDirectory = NO;

        if (![[NSFileManager defaultManager]
    createDirectoryAtPath:packagePath attributes:nil]) {
            // create an error
            return NO;
        }

        return [super writeToURL:absoluteURL ofType:typeName
    forSaveOperation:saveOperation
    originalContentsURL:absoluteOriginalContentsURL error:error];
    }

    --
    Seth Willits
  • >>> >
    >>>
    >>
    >> I'm not sure how that was supposed to be helpful given that I had
    >> already read the documentation (not to mention the tutorials,
    >> sample code, Google, and the list archives) and came here asking
    >> for further help.

    You clearly didn't read closely enough - the reference states (and I
    think it's mentioned elsewhere) that NSPersistentDocument doesn't
    support file wrappers...

    >> As it turns out, overriding readFromURL:/writeToURL: and
    >> configurePersistentStoreCoordinatorForURL: is working dandily so far.

    It will almost certainly fail at some point -- probably during a revert.

    mmalc
  • On Jul 3, 2007, at 1:38 AM, Seth Willits wrote:
    > My document-based app has a document type which uses a package
    > instead of just a single file to store data in, because there is a
    > need to store related files inside the package as well. Currently
    > I'm doing some relatively simple overloading of standard NSDocument
    > methods to open and save the database by using a path based off of
    > the -fileName.

      One major problem with using file wrappers is ensuring atomic
    saves.  If one of your save operations needs to update SQLite and add/
    remove/update other files in the file wrapper, the only real option
    would be to make a copy of the entire wrapper, apply the changes
    (including the SQLite transaction) to the copy and then atomic swap
    the two wrapper directories using FSExchangeObjects or the like.  At
    this point, you've lost most of the benefit of putting it in a SQLite
    database (at least in terms of save speed; there are obviously other
    benefits).

      What I wouldn't give for a transactional filesystem with copy-on-
    write...

    -tim
  • On Jul 3, 2007, at 1:42 PM, Seth Willits wrote:

    > As it turns out, overriding readFromURL:/writeToURL: and
    > configurePersistentStoreCoordinatorForURL: is working dandily so
    > far...

    ... until you try to save the second time. :)

    I continued to fiddle with readFromURL/writeToURL and tried to get it
    to work (I added the store myself from
    configurePersistentStoreCoordinatorForURL), but no matter what I did,
    I always end up with crash when doing a second save caused by super's
    implementation of writeToURL: returning NO but not setting the
    outError causing a crash when it tries to display the error. Nothing
    in the log, and NSZombie didn't catch anything either. Wonderful!

    So I'm back at square 1 basically.

    I'm currently fiddling with an NSDocument subclass, but I'm sure I'll
    hit a wall eventually...

    --
    Seth Willits
  • On Jul 3, 2007, at 3:38 AM, Seth Willits wrote:

    > I'm taking the plunge and switching a fair chunk of code to using
    > Core Data instead of my own management of an SQLite database. At
    > least that's the current plan. ;)
    >
    > My document-based app has a document type which uses a package
    > instead of just a single file to store data in, because there is a
    > need to store related files inside the package as well. Currently
    > I'm doing some relatively simple overloading of standard NSDocument
    > methods to open and save the database by using a path based off of
    > the -fileName.
    >
    > With NSPersistentDocument, by default it uses the document's -
    > fileName as the path for the persistent store. What is the best way
    > to retarget it so that it uses a different path within the package?
    > I imagine someone here must have done it, so I'm hoping to not have
    > to fiddle for so long to figure it out, however it seems that I
    > might simply be able to override
    > configurePersistentStoreCoordinatorForURL:ofType:error: and pass a
    > different URL to super's implementation? Will there be any side
    > effects to this?

    Seth,

    I've thought about having files associated with my Core Data database
    as well and I came up with a different solution that may work for you
    as well. Instead of trying to keep the files with the database, you
    could designate a folder as a repository for the files. This can even
    be a user-preference to relocate this folder. This way you avoid all
    the stress of trying to roll them into the database.

    The other option, if the files are small enough, is to actually store
    them in a Binary Data field of a database table.

    Peace,

    Kevin Hoctor
    <kevin...>
    No Thirst Software LLC
    http://nothirst.com
previous month july 2007 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today
MindNode
MindNode offered a free license !