Store very small sound files with core data - ios

I saw in other posts that it is O.K to store small image files (less then 50 kb) as a binary data inside core data. is it true for sound files that are less then 20 kb?
Thanks
Shani

There's no difference between sound files, image files or any other binary data as far as Core Data is concerned. Under 20kB I would store in Core Data unless you have a good reason not to (such as caching as mentioned), but I would store them as a separate entity if you are not accessing them every time you access an object.
The general rule of thumb I've seen mentioned is <10kB store on the entity, >10kB but <100kB store in a separate entity and >100kB store in the file system.

I store data like this in the file system and I keep the path to the file in my core data object. This lets me optionally use a class that caches lookup of the images that can be emptied if the program receives memory warnings.
You should read the apple's "Core Data Performance" document, specifically the section on Large Data Objects.

Related

Why does a ~0.5MB binary file take up 4.3MB of iCloud space when stored in a Core Data record?

The situation
I am using Core Data's "Allows External Storage" to store compressed images and small audio files in Core Data. Performance benchmarks have shown that this is actually quite performant. Also, I am using Core Data's PersistentCloudKitContainer to sync my database with iCloud.
"Allows External storage" will automatically save files that are bigger than ~500KB (?) to the file system and only store a reference in the database. This works nicely. For instance, a 1MB image file is stored as an external record and takes up the expected 1MB of iCloud storage after syncing. Also, files that are smaller than those ~500KB are not stored as external record (ckAsset), but as binaryData in the database record.
The problem:
For some reason a 0.47MB binary data file that is stored directly in the database will take up about 4.3MB of iCloud storage. That is 9x of the expected amount. Inspecting the binary data stored in the record shows that the binary data itself has the expected size of only 0.47MB (CloudKit Dashboard). Also, I have verified that the local app bundle only grows by the expected 0.47MB. Thus, how can those additional 3.8MB of consumed iCloud storage be explained? In contrast, audio and image files that are larger than ~500KB are stored as external records and take up the correct amount of iCloud storage.
Please look at this annotated image for a better understanding:
Image that illustrates the problem (CloudKit Dashboard)
Ideas / Workarounds / What I tried:
I could try to find a way to always store files as ckAssets/external records. (e.g. by lowering the limit for storing ckAssets to 0.01MB). If that is possible.
Could the Write-Ahead-Log (WAL) of SQLite be involved in creating huge temporary sqlite-wal files? I tried limiting the WAL journal size and the local sqlite-wal is small, so I don't think that this is where the problem lies. Unless there is an independent iCloud WAL file that I don't know about.
I would be glad if anyone could help me with this issue. Thanks in advance!

Save images in Core Data + iCloud - Swift

My app is a mood diary and to save data I've chosen to use Core Data (for strings, images, etc.); to allow the user to restore his diary I've implemented iCloud, that works well with Core Data.
Everything works well if I have not much entries, but when the images saved are too much the app is slow to load data and encounters memory warnings.
To save my images I've chosen Transformable data type and not Binary Data; I know that is not the best way to save images (saving url is surely better), but I need to sync my data on iCloud, and saving images as Transformable allows me to sync data in a simple way (thanks to the possibility offered by Apple Api to link Core Data and iCloud).
What can I do to avoid this memory warnings and sync my app pics on iCloud?
I've considered the possibility to save my pics on a custom photo album (if iCloud is activated for Photo app my app pics would be synchronized), but I need to save them with custom name to retrieve them from camera roll to my app, and for the moment I don't find any solution to save pic with custom name in a custom photo album.
Saving photos in document directory (and saving urls in my core data entity) would be the right choice for local database, but my app pics would not be synchronized.
There are a few things you can try.
First, add an image thumbnail property which stores a smaller version of the image. Use that whenever possible. Loading a bunch of full-size photos needs a lot of memory, so change to loading smaller images whenever your UI allows smaller sizes.
Beyond that you can change how you handle images using one of the following strategies. In ascending order of complexity (and effectiveness):
Make sure "Allows external storage" is enabled for the image property in your data model. This will let Core Data put the images outside the persistent store without requiring you to manage those files. This will save on memory if, for example, you sometimes fetch data but aren't using the image property.
Change the data model so that the image is saved in a different entity, with a relationship linking it to your current entity. This should make it easier to avoid "accidentally" loading images when you're not using them.
Put the images in separate files and keep only the file names in Core Data. You can still sync the images via iCloud, because you can sync files directly via iCloud outside of Core Data. But you'll need extra code to manage uploading/downloading the images. You'll also need to make sure you can handle the case where Core Data has finished syncing but the image is not available yet.
On this list, #1 is easiest but will probably have the least effect. Using #3 should be very effective but will require the most work.

How to store many images and .mp3 files in core data for iphone?

I am very new to core data and am trying to learn how to store large files, like images and short .mp3s. My app has about 300 different images and short .mp3s that are triggered to be displayed/played by user interaction, and as far as I can tell, I should use core data for storing these files.
I added a core data .xc file to my xcode project, and created an entity with attributes. I chose an attribute named "binary data" and checked the box "Allows External Storage," which from what I've read allows me to easily persistently sore files on 5.x or newer iOS phones. I know that I can program the app to get and set these attributes, but how do I just store my images and music files here?
Please help with me with code/understanding. It seems to me I should be able to somehow use the core data interface to set up a bunch of entities containing attributes of "binary data" that are my images and .mp3s, and whenever I need to display a pic or play a sound, I could call the entity and its attributes.
Thanks for the help!
I store compressed images (jpegs) with Core Data and it seems fast enough. But these are compressed to < 100K.
If you want to store items bigger than 100K, you might want to just save the file to "disk" doing something along the lines of Write a file on iOS
Then, save the file path to a string in Core Data. To load the file, get the file path from core data then read the file in.
I think Apple recommends the cutoff at 100K.

iOS: using iCloud document storage for a small XML based database

Just wanted to know if this is a good idea:
I want to use iCloud to sync data between different devices in my iOS app. It's just a list of small objects without connections. But storing this list in the key/value store won't work because it's space is restricted to 1 MB or so and the list might get bigger (not much, but could...). Core data seems like an overkill to me and there is also the problem of possible duplicates.
So I wonder if it makes sense to subclass UIDocument to handle the XML file. Every object has an ID, so merging different versions of the file should be no problem.
The choice of XML depends on the format of the data store (monolithic or transactions) and the volume of updates. If the entire file (1 MB+) is constantly being written to by your app (and hence sync'ed to iCloud) or if a small change causes the entire store to be sync'ed to iCloud then I would use Core Data. The advantage of core data is that only the transaction logs you require (or have changed) are synced.

Storing blobs in external location using built-in CoreData option

I have managed objects that have image properties. Since storing large blobs in CoreData is a bad idea, I'm trying to use the built-in CoreData option "Store in External Record File" which you can see in the Data Model Inspector.
Despite enabling this option, I do not see any image data being stored externally. Judging by the size, it seems like they are still being saved in the sqlite file. What is the issue?
If your store type is NSSQLiteStoreType, your attribute is NSBinaryDataAttributeType. You have enabled setAllowsExternalBinaryDataStorage and your object data size is larger then approximately 1MB.
Objects that are smaller than 1MB are stored in the sqlite database.
Objects that are larger are just a reference to a external file.
You'll find the (external) files in a hidden sub-directory at the same location as the persistent store.
<path>/<database>.sqlite
<path>/<your_database>_SUPPORT/_EXTERNAL_DATA/
sqlite2 does not allow size of BLOB data to be more than 1MB,However sqlite 3 allows larger BLOB.First check out which version of sqlite u r using.
And if ur file is in MB's i would rather prefer them storing in local database instead.

Resources