5
votes

Im on iOS 7 and want to use core data with iCloud, this is working well, the issue I wanted some input on is the following.

Some of my Core Data objects have related images/large text files which I was storing as files on the file system and just setting the url of these items as string properties. Now obviously this wont just work with iCloud Core Data sync because iCloud has no notion of these files. I was wondering if you had any suggestions on how to handle this?

1) I could store the image data and large text files as core data properties directly but it does not seem to be the best way to go

2) I could use iCloud to also store the documents and then somehow try to keep sync between the files in different iOS devices, but this could potentially get messy.

3) Some other solution.

Any Suggestions?

Regards

Daniel

2
are you open to any 3rd party tools for this. I have a friend who has done this exact thing brilliantly and offers a service for doing this.logixologist
You have link with info on this 3rd party tool?Daniel
Yes... its by @Jiva DeVoe: stackoverflow.com/users/705569/jiva-devoe called Wasabi Sync.logixologist
Is there a reason you don't just store them as attributes in core data? I use transformable attributes to store rich text with embedded images, some of which are 8mb jpegs. Seems to work fine but the largest database is around 100mb. It would be just as easy to store the images and text separately in the same way.Duncan Groenewald

2 Answers

5
votes

If you are setting up the model programmatically, add a message to setAllowsExternalBinaryDataStorage: to allow Core Data to decide when to save it as a record or separate file automatically. Core Data manages the external files for you when it decides to use them, so it should "just work" in iCloud as well.

NSAttributeDescription * imageAttribute;
//Initialise, setup, add to model, etc
[imageAttribute setAttributeType: NSBinaryDataAttributeType];
[imageAttribute setAllowsExternalBinaryDataStorage:YES];

There is a corresponding checkbox for the attribute in the model editor UI as well.

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSAttributeDescription_Class/reference.html#//apple_ref/doc/uid/TP30001175-SW26

3
votes

Place the files in your iCloud document sandbox also and they will keep synced across all your devices.

You can use a relative reference to the items as they will appear in the file system at the same relative point.

<ubiquitous container URL>/Documents/something.jpg

A minor issue is that the sync isn't seamless and you will have to explicitly request the item to be downloaded from iCloud if it isn't on device already.

So at its most primitive...

NSDictionary *dict = [urlToIcloudResource resourceValuesForKeys:@[NSURLUbiquitousItemIsDownloadedKey] error:&error];

NSNumber *isDownloaded = dict[NSURLUbiquitousItemIsDownloadedKey];

if (![isDownloaded boolValue]) {
   BOOL res = [[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:urlToIcloudResource error:&error];
}

So you can keep using your current strategy of dumping them in the file system and just using a string reference to them. iCloud will keep them synced.

The suitability of this solution does depend on whether those large blobs are write-once-read-many objects (very suitable) or read-write-often type objects (trickier).

One advantage is that for text objects like txt or json if you keep the extension on the file iCloud should "just work" for keeping multiple device edits in sync.

Raw data objects like jpg or pdf will be last edit wins.