Best way to save video in iOS Application for offline viewing - ios

I'm in state of confusion that "What would be the best way to store video?" locally downloaded from the server.
I have two versions of same app i.e online and other offline.
For offline mode I want to download all the videos locally for watching them offline in future.
I know that there are two ways of storing videos:
Feasible way would be storing it in document directory of the application and save the corresponding video file name in the sqlite database. But, there are around 200+ videos!
I just fear it might create memory problem, giving my application memory warning and make it to crash.
Storing it in NSData format in sqlite database, but it would make the database huge which I think would not be feasible as sqlite db is meant to be light weight.
Is there some other way that we can accomplish the task. (And as per the requirement videos should not be save in the gallery on the device).
Please help me!
Thanks!

As far as I know, the document directory is your only option. It should not effect the memory, however, please keep in mind that if you app gets deleted, this directory will be as well.
I have recently built an app that relied on saving videos to the Document directory and we ran in to no problems.
I would avoid storing large assets in a Database. You gain no benefit from this and these videos will still be lost if the app is deleted.

You can save any kind of files, anywhere in your application environment directories using...
[[NSFileManager defaultManager] moveItemAtPath:[/*Your current file path*/] toPath:/*Your destination path*/ error:/* &errorObj */];
OR
[[NSFileManager defaultManager] copyItemAtPath:[/*Your current file path*/] toPath:/*Your destination path*/ error:/* &errorObj */];
and for moving 200+ files... you can use a naming convention from which you can handle it using any kind of loops.
Note :
1. For any kind of large in size files, I always use this way, rather than saving in any kind of databases.
2. One should always use "move" operation while downloading the files.

Related

How to best move a huge .sqlite database to a new directory on an old, low memory iOS device?

For my latest app update, I have to move the user's Core Data .sqlite database from the Documents directory to the Application Support directory. I use the migratePersistentStore:toURL:options:withType:error: method. I am dealing with one user who somehow managed to save enough data in her database so that it is now a whopping 9G. On top of that, her device is an iPad Air 1 - which had memory issues around the time it came out five or six years ago, and now it is 2018 and she is running the latest iOS. The migratePersistentStore:toURL:options:withType:error: method keeps crashing the app with low memory. But I have no other way to get the .sqlite to the necessary location. Can anyone advise me on how to best approach this situation? Ideally, something I could do in my code - but I would even appreciate suggestions on other ways I could just help the user to manually move that massive database at this point!
I guess you use migratePersistentStore because its the official way to do it. Its a good way, but sometimes you have to make your hands dirty:
Manually-moving database at app-start before you load it
This post shows that CoreData may use more than one file which you have to move. You can list the files in the directory, use a regex find all the files which have to be moved, move them to the new location and then load CoreData as usual from the new location.
This however requires there to be the necessary infrastructure in place to do this. You‘ll figure it out if you want to go this path.
You can hide this behind a feature-flag, only with a code, only for a certain user or after crashing with low memory so it doesn‘t impact users who don‘t need it.

save image and videos within the app iOS

I want users to save the picked image and video within the app. So I wanted to know what is the best. Should i convert the picked images and videos to NSData and save in Core data? I search everywhere and everyone recommend to use Documents Folder to save images and videos because coredata is slower. I just started learning CoreData so I don't have much knowledge about it. Here is what I have come up.
Users pick the image or video -> App Saves it to documents folder -> Using coredata, application stores the filepath as string to access the image or video. (and User can backup anytime using icloud)
and Users can access those files in their other devices using iCloud. Please explain me if I'm incorrect or if you have better alternative or the question is wrong in any way. Thanks
I've done both ways and for me it's just a matter of how to use the database. If you'd like to to be able to backup the database and share with other, I would recommend storing files in CoreData as NSData. If it's just a local database it might be easier to store URL's to images stored on disk.
When you setup a Binery field in CoreData you can optionally select "Allows External Storage" which basically store the file on disk for you, but you can load it from the databas as if it was stored in the db. This is what I use most for images.
With this option, it is easy to create a zip file of the database and all binary files connected to it and also easy to unzip it to make a restore of the database.

Solution For Monitoring and Maintaining App's Size on Disc

I'm building an app that makes extensive use of CoreData and a lot of my models have UIImage and NSData properties (for images and videos). Since it's not a great idea to store that data directly into CoreData, I built a file manager class that writes the files into different buckets in the documents directory depends on the context in which was created and media type.
My question now is how do I manage the documents directory? Is there a way to detect how much space the app has used up out of its total allocated space? Additionally, what is the best way to go about cleaning those directories; do I check every time a file is written or only on app launch, ect ect.
Is there a way to detect how much space the app has used up out of its total allocated space?
Apps don't have a limit on total allocated space, they're limited by the amount of space on the device. You can find out how much space you're using for these files by using NSFileManager to scan the directories. There are several methods that do this in different ways-- check out enumeratorAtPath:, for example. For each file, use a method like attributesOfItemAtPath:error: to get the file size.
Better would be to track the file sizes as you create and delete files. Keep a running total, stored in user defaults. When you create a new file, increase it by the amount of new data. When you remove a file, decrease the running total.
Additionally, what is the best way to go about cleaning those directories; do I check every time a file is written or only on app launch, ect ect.
If these files are local data that's inherently part of the associated Core Data object, the sensible approach is to delete a file when its Core Data object is deleted. The managed object needs the data file, so don't delete the file if you still use the object. That means there must be some way to link the two, but I'm assuming that's already true since you say that these files are used by managed objects somehow.
If the files are something like cached data that's easily re-created or re-downloaded, you should put them in the location returned by NSTemporaryDirectory(). Then iOS can delete them when it thinks the space is needed. You can also clear out old files whenever it seems appropriate, by scanning for older files or ones that haven't been used in a while (the details depend on exactly how you use the files).

What do ios apps do when they 'load?'

Most apps I see have loading screens, presumably to prevent hiccups in the game and to pre-load all of the data needed later in the game. I am currently working on a game that skips every few frames, presumably because the image data for the objects being rendered to the screen are not being held in memory. What do programmers actually do to hold this data in memory throughout the time the app is running? I can think of using arrays, such as NSArray or NSMutableArray to hold the images, however I still struggle to see how that would improve the performance of the app. Perhaps I am totally going off on a tangent here. A word of advice from someone with experience in the area would be greatly appreciated.
EDIT:
For the person who voted to close the question, my question, more specifically, is this: What is a typical method in which an ios game loads its data into active memory to enable easy and low-overhead access during run time?
I have seen several application that downloads configuration and metadata on application load, some also download images and audio files.
Usually they store the data in the documents or cache folder, so the they will not have to wait for download during the game.
Another technique I encountered is downloading a zip file and expanding it in the cache directory. Most of these apps do not load the files the next time unless something new is needed.
Do not load the images to the memory, not inside an nsarray nor nsmutabearray. You do not have enough memory to cache images like this. You should just predownload them
Edit:
You can use the application loading stage to download more resources from your servers (images, audio, plist files) but after they are download and stored in the file system they should be treated like resources that exists in your IPA. They should be loaded into memory only when they are needed

iCloud with Core Data and File sync

I'm working on an Application that uses Core Data with iCloud (with the great improvement given by iOS7). This application stores data to describe a task with this information:
name a NSString
date a NSDate
image a NSString which describes a path to the picture
The pictures could be stored in Documents or Library Directory (I have to decide which is the more convenient folder), by the way, in the same folder with a unique name.
Now I'd like to activate iCloud sync for the images too otherwise the experience of the user will be incomplete (I just sync DB data.. no images, a strange/wrong behaviour for an app).
I'm really confused by Apple Documentation. I can't find a way to understand exactly how iCloud data works for this kind of needs. I just want to sync every file of a folder as soon as they will be created. So my questions are:
Could you share some good resources to learn how to use iCloud for file sync
Have I to use UIDocument and other iCloud API? or is there something "automatic". Quite a new bye/stupid question, I know :(
Are there any problem using Core Data and Document based iCloud synch in the same app?
Note: I know that I can sync data just by adding file in the document folder and hoping that users activate document sync... but this is not what I want obviously.
It is pretty straight forward to use both Core Data transaction log synchronisation and file based synchronisation in the same app to achieve what you want to achieve.
So you would set up your Core Data stack to use iCloud options and synchronise data changes via iCloud. At the same time you would store your images in the Apps iCloud container so they get synchronised as well. Just remember you need to use a relative reference to the images in your Core Data fileURL because the full pathname will vary depending on the device the app is running on. So for example you would just store the image filename in Core Data and use a standard directory such as 'iCloudContainer/Documents/Images/' to store them. 'iCloudContainer' being the URL you get by calling the [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:] API.
I have uploaded sample Core Data apps that use iCloud for transaction log synchronisation (i.e. synchronising data in Core Data) and that use file synchronisation for storing Core Data backup files in iCloud which can then be accessed by any device. You should be able to use the same code for moving backup files to and from iCloud for your images. Just remember you have to trigger download of files from iCloud before you can use them either by doing a coordinated read or by initialising the download using NSFileManager.
http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/
http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/sample-apps-explanations/
Download and run the sample apps and use the built in Backup File Manager to make backup files and to copy them to and from iCloud using different devices. Then just use the same code when storing your image files.
Your App does have to handle things like the user changing iCloud account, logging into or out of iCloud etc. and them move the core data file and image files accordingly.
The only way to have this happen automatically is to create a binary data attribute in your model for the images. If you do this, you will probably want to check the external binary storage allowed option, so the photos end up stored as files and not in the database.
If you would rather store the photos external to your store, you will have to do more work. You will need to migrate the photos into the iCloud container yourself, using the NSFileManager methods, for example. You could also use a class like iCloud Access if you find that easier.
The downside to handling the photos yourself is that you can never be sure that they have all arrived on your device when the Core Data store syncs, so it could be one or more photos are missing, even though there are entries for them in the store. You would have to make sure your app could handle this scenario, perhaps showing a placeholder image until the real photo was accessible.
There are no issues using Core Data and Document syncing in one app. In fact, they are exactly the same under the covers. From iClouds point of view, they are all just files to be transferred.

Resources