I am downloading a mp4 file with my iOS app, it works fine using
NSData dataWithContentsOfURL
but i need to updated only if the file has been updated,
can I check the file headers? or what is the best way to determine if the file has been updated so I downloaded it again?
Thanks
You can access the metadata using the http HEAD request, as explained in this SO answer. You'll need to create some sort of parser to pick out the information you need, though. Note that this might not work with every server, depending on how it has been set up.
If you have control of the server yourself, I'd recommend using a php script to output the date the file has been last changed, which you would call before downloading the file.
Personally, I prefer placing a manifest file (usually a plist) alongside the file in question, as it can hold even more data, for example metadata for several files, the number of entries in a database and the like. A backdraw of this approach is that you'll need to keep this file up to date, though. But often, that is worth the while.
Lastly, as rckoenes has mentioned, dataWithContentsOfURL is not a very good way to download files, espcially large ones. You really should be using some sort of datamanager class, which manages a NSURLConnection.
Related
I have an app that is using NSFileWrapper to create a backup of the user's data. This backup file contains text and media files (compression is not relevant here). Sometimes these backup files get quite large, over 200 MB in size. When I call NSFileWrapper -writeToURL... it appears to load the entire contents into memory as part of the writing process. On older devices, this causes my app to be terminated by the system due to memory constraints.
Is there a simple way to avoid having NSFileWrapper load everything into memory? I've read through every NSFileWrapper question on here that I could find. Any suggestions on how to tackle this?
Here is the current file structure of the backup file:
BackupContents.backupxyz
user.txt
- folder1
- audio files
asdf.caf
asdf2.caf
- folder2
- audio files
asdf3.caf
Again, please don't tell me to compress my audio files. That would only be a band-aid to a flawed design.
It seems like I could just move/copy all of the files into a directory using NSFileManager and then make that directory a package. Should I go down that path?
When an NSFileWrapper tree gets written out to disk, it will attempt to perform a hard-link of the original file to the the new location, but only if you supply a parameter for the originalContentsURL.
It sounds like you're constructing the file wrapper programmatically (for the backup scenario), so your files are probably scattered all over the filesystem. This would mean that when you writeToURL, you don't have an originalContentsURL. This means the hard-link logic is going to get skipped, and the file will get loaded so it can get rewritten.
So, if you want the hard-linking behavior, you need to find a way to provide an originalContentsURL. This is most easily done by supplying an appropriate URL to the initial writeToURL call.
Alternatively, you could try subclassing NSFileWrapper for regular files, and giving them an NSURL that they internally hang on to. You'd need to override writeToURL to pass this new URL up to super, but that URL should be enough to trigger the hard-link code. You'd want to then use this subclass of NSFileWrapper for the large files you want hard-linked in to place.
I got an app I'm working on that uses static data from a sqlite database to do various things, While I only need read only access to the database, depending on the episode they pick from the first screen I want it to use a different database file and I want the list of available episodes to be updateable on the fly. and I got help to get the list of available episodes updated, and the proper content downloaded and stored in separate folders, So I know I could when the episode is selected delete the sql file in the documents folder and copy in the new one each time and that would work well enough for what I'm trying to do. but it seems like a bit much extra work to have to check for file, delete file, copy in new one. then open it from there each time the user wants to pick a different episode. and I don't want to put all the sql files together as that will be a bigger hassle then the first route especially if this app stays around long enough to have a long list of episodes.
so my question here is: can I get at least read-only access to an sql file that I've downloaded (or one in the bundle for testing) with out having to first copy it to the documents? and if so how would i open the file?
Can I get at least read-only access to an SQL file that I've downloaded (or one in the bundle for testing) without having to first copy it to the documents directory?
Yes. Files in the app bundle are readable (if they weren't, there would be no point in storing files in the bundle).
And if so, how would I open the file?
It's not clear what you're asking here - if you want to perform SQL queries on the file, you should use the sqlite3 library which is available on iOS.
I am doing something with core data. Since the original sqlite file contains the data in the application. I decide to do the following:
Separate the reading and writing action. Make all the reading from one data source of one sqlite file and make all the writing in another file.
Since there are some rules in the directory in iOS application, I plan to copy all the reading data from bundle to the cache directory and put the writing data in the document directory.
The question is that, is it possible to use the reading file in the bundle resource directly. Which means I don't have to copy it into the cache file and that will save some space for the device.
Or you guys have any other better idea, please tell me.
I put the write data into the document because the file in it can be backuped by icloud, which could act as a feature in my program.
You ask if what you want to do is a good idea, but first you need to think through some possible pitfalls.
I suppose the file in your bundle was also created with Core Data, and it has a MOM. The new file you write - it probably uses the same MOM. What will you do if you ever need to update the MOM? The file on iCloud will be say version 1, and maybe the users iPhone uses Version 1, but your new version 2 is loaded onto the users iPad. Now what? The ipad should not update the repository as that would make the iPhone fail when it tries to use the data - the ipad has no way of knowing if all other devices have updated or not.
I am creating a database application using the SQLite3 library.
I have created a database file using each of the file extensions: .db, .sqlite, and .sql.
All are working fine for me, but my question is which extension should I use in general?
Is there any difference between these file extentions?
The Sqlite documentation seems to use the '.db' extension consistently, but I've seen plenty of Sqlite files that use '.sqlite' instead. Use whatever is meaningful to you. For example, if you're using Core Data to create the database, you might use '.cd' or .'coredata' to remind yourself not to modify the database outside of Core Data. Unless you're planning to transfer the file to some other machine (and really, even then) it won't matter.
The database will live in your application's sandbox, so users will never have to know about the filename or the extension, and other applications typically won't ever see it either. Just give it a distinct name so you can tell it apart from other files that your app might be saving to the same location.
I currently have a large .sqlite data store of long string text. It's about 160MB and will grow to about 200MB when I'm completely done. This is a "read only" data set.
What I do now is simply place that file in my bundle and read it during runtime. However, that means the app requires you to download 160MB. Not optimal.
One solution is to gzip that file, ship the gzipped version in the bundle, uncompress it on first run, and put it in the Documents/ folder. This means you'd download far less, but the total size the app uses on the device is (size of gzip'd + size of ungzip'd) which is obviously not optimal either.
I want to use the gzip solution, but after application's first run, I want to delete the .gz version. Is this possible? How do I achieve it? What would another good solution be?
It is not possible to delete a file in the bundle. The app must be signed and if the bundle is modified in any way, it will not pass the signature.
The only other solution I can think of, is to setup a web service, and have your app download portions of your content as necessary. This may or may not be a viable solution, depending on what your app is actually doing.
As Paul says, anything in your bundle is part of the signature.
I can't see this changing as it is a fundamental part of signing apps.
The other classic approach is to compress the data in your bundle, as heavily as possible, so you unpack it when you build the working storage.