drewmccormack / ensembles

A synchronization framework for Core Data.
MIT License
1.63k stars 131 forks source link

Handle large binary objects #100

Closed drewmccormack closed 10 years ago

drewmccormack commented 10 years ago

At the moment, NSData objects are included directly in the event store and cloud event files. If these are large, it could be a problem.

Large NSData, and possibly large NSString, should be stored in separate files. These will have a UUID. A Blob entity will be needed to track them in relation to CDEObjectChange.

inPhilly commented 10 years ago

Given how you have decided to handle large images, what do you think is the best way to store images in Core Data, if the images are strongly related to their respective records? 1) Transformable, 2) Binary Data/Allows External Storage or 3) storing the images in their own files, and saving the URL to those files inside the database? Does using any of the three of these options make it difficult or impossible to use ensembles? I guess I am asking if there is a 'preferred' and/or 'prohibited' way of image store for ensembles.

drewmccormack commented 10 years ago

There isn't really an ideal approach. You will have to decide what is best for you and your app. It depends to some extent on how important the images are. Whether they are essential to the data.

Each approach has downsides. When you store with a transformable, Ensembles will ensure the data is available when you get the merge notification. That's the upside. The downside with transformables is that you will nearly always have to copy the data into a temporary external file to use it. Eg. To load a PNG image or some audio, you have to copy the data to a file with the appropriate extension, then use a framework to load it.

The approach of storing your files externally in an image store has the advantage that this copy of data is not needed. You can load the files directly. The downside is that they will not be under the control of Ensembles, so they may arrive later. You thus have to make sure your app can handle the case where it knows about an image, but the image hasn't arrived yet.

If you were making an app like keynote, where putting image placeholders is not really acceptable, I would probably use the transformable approach. If you are making an app where images are used for avatars, and not essential, I would use the image store approach, and just show a placeholder when the file is not available.

If you want to use an image store, you can use the CDEICloudFileSystem to transfer the files. Just make an extra directory in the cloud, and upload to that. This is probably easier than doing your own networking, and will be portable across backends (e.g. iCloud, Dropbox).

inPhilly commented 10 years ago

Thank you Drew. That was very helpful. In any case, it seems like the second option (Binary Data/check the Allows External Storage box) is not advisable - right? Doesn't that lead to problems in the cloud? Accordring to this article: http://www.objc.io/issue-10/icloud-core-data.html "External file references is a feature introduced for Core Data in iOS 5 that allows large binary data properties to be automatically stored outside the SQLite database on the file system. In our testing, when this occurs, iCloud does not always know how to resolve the relationship and can throw exceptions. If you plan to use iCloud syncing, consider unchecking this box (allows external storage) in your iCloud entities."

drewmccormack commented 10 years ago

That article relates to iCloud-Core Data. If you use Ensembles, there are none of those issues.

(To be honest, I never had those problems even with iCloud-Core Data, so maybe it is a recent bug.)

inPhilly commented 10 years ago

Doesn't ensembles integrate Core Data and iCloud? Sorry if I am misunderstanding.

drewmccormack commented 10 years ago

Yes, Ensembles is a framework to sync your Core Data via iCloud, but Apple also has built in Core Data sync.

The article refers to the built in Core Data sync. Ensembles is a separate framework, and doesn't use the built in Core Data sync.

Drew

inPhilly commented 10 years ago

Thanks so much.