I have a app that downloads video and image files from a server. I store these files in folders in my app. I have 3 different places where i store the files:
Caches Directory - Videos + Images downloaded
Application Support Directory - Database
Documents Directory - Videos taken by current user
The code that i use to get paths to these folders is:
+ (NSString *)FilesStoreDirectory
{
NSArray *paths = [[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask];
NSString *path = paths.count ? [(NSURL *)paths.firstObject path] : NSTemporaryDirectory();
NSString *result = [path stringByAppendingPathComponent:#"files"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:result])
{
[fileManager createDirectoryAtPath:result withIntermediateDirectories:YES attributes:nil error:nil];
}
return result;
}
At the logout i remove all these folders and files. The database (sql) is the only file that is not deleted.
My problem is that the size of the app increases while use. I have a example of 4 GB of stored files and after logout it went down to 1.9 GB when it should only be 23 MB + database (small). The way that a check how big is the app is by checking Settings -> Usage.
I am thinking maybe there is a problem with the folder creation and it creates different folders between different runs of the app, but that didn't solve the problem.
I play these video files so i suspect the AVPlayer of caching these files and not letting them go. But that is just a hunch.
Anybody has a idea why this is happening, and how can i get back to 23 MB of app size?
Thanks.
LATER EDIT:
This is the code that i use to remove the folders:
[[NSFileManager defaultManager] removeItemAtPath:[LVCoreDataController FilesStoreDirectory] error:nil];
Related
I'm trying to create a folder in my documents directory and I want to be able to do it without typing out /Users/(username)/Documents/Foo/Bar
NSString *directoryPath = [NSString stringWithFormat:#"%#/Documents/Foo/Bar", NSHomeDirectory()];
BOOL isDir;
NSFileManager *fileManager= [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:directoryPath isDirectory:&isDir])
if(![fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:NULL])
NSLog(#"Error: Create folder failed %#", directoryPath);
This doesn't work when I try using NSHomeDirectory() with it. But if I typed out the full path /Users/(username)/Documents/Foo/Ba it works. How can it be done to not have to know the users folder?
EDIT:
directoryPath becomes
/Users/(username)/Library/Developer/CoreSimulator/Devices/FAB78255-38D2-49BE-9683-7A0676EA2288/data/Containers/Data/Application/67B0AACE-572A-4808-9535-D221AEEB9EFA/Foo/Bar
I just want /Users/(username)
This is an iOS app. The "Documents" folder of an iOS app's sandbox is not at all related to the user's "Documents" folder on their computer.
Since you appear to be running your iOS in the simulator, the path you are getting is more like what you should be seeing. You do not want a path in the user's home directory.
Keep in mind that you can't get access to the "Documents" folder of an iOS app using NSHomeDirectory(). That may have worked in older versions of iOS but it fails in iOS 8 and later. The proper code needs to be something like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsFolder = paths[0];
NSString *directoryPath = [documentsFolder stringByAppendingPathComponent:#"Foo/Bar"];
My app uses iTunes File Share. I used the code to delete a single file:
It worked the first time. On the second try, however, iTunes showed a empty share directory. It turns out all data files are gone. Can I recover those data files from the iPad? Thanks
- (void) deleteFileFromDisk: (NSString*) fileName {
if([self fileExists: fileName]) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ;
NSString *documentsDirectory = [paths objectAtIndex: 0];
NSString* theFile = [documentsDirectory stringByAppendingPathComponent: fileName];
NSError *error;
[[NSFileManager defaultManager] removeItemAtPath: theFile error: &error];
There's no "restore" feature on the iPad. But in all probability there's nothing to worry about.
There's nothing about your code that would delete multiple files. It would delete just that file from the Documents directory that you supplied the name of as fileName. If you didn't call deleteFileFromDisk: multiple times, you didn't delete multiple files.
Perhaps at some point you deleted the app. That would delete its entire sandbox and thus would take with it anything in the Documents directory. That sort of thing is perfectly normal during repeated testing.
I've looked through the Apple documentation on this point and other questions here, but cannot find a means of getting a consistent path to the documents directory.
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *urls = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *directory = [urls lastObject];
This produces a different path each time due to one component.
Example:
file:///var/mobile/Containers/Data/Application/CA708CF5-0E1B-414D-A795-31A8BB884BA5/Documents
Next run:
file:///var/mobile/Containers/Data/Application/2C96E341-85EF-485D-AC19-F8844B0880C3/Documents
I realize I need some kind of relative path here but I cannot figure out how to get it. How can I get to the Documents directory consistently to both write and read a file my app will produce?
The path is determined on installation. Each time you run your app in the simulator, it will be removed and reinstalled. Hence the differernt path. So you don't need to worry about this.
I am using NSKeyedArchiver and NSKeyedUnarchiver to implement cache function for my app.
In order to load the cache file each time the app launches, I store the cache file under NSHomeDirectory(). The code (C function) is as following:
NSString* getArchivePathForId(NSString* modelId)
{
NSString *cacheIdentifier = #"CacheIdentifier";
NSString *archiveDirPath = [NSHomeDirectory() stringByAppendingFormat:#"/tmp/%#/cachedModel/%#", getAppVersion(), cacheIdentifier];
NSError* error;
if (![[NSFileManager defaultManager] fileExistsAtPath:archiveDirPath]) {
if (![[NSFileManager defaultManager] createDirectoryAtPath:archiveDirPath
withIntermediateDirectories:YES
attributes:nil
error:&error])
{
NSLog(#"Create directory tmp/cachedModel directory error: %#", error);
return nil;
}
}
NSString *archivePath = [archiveDirPath stringByAppendingFormat:#"/%#", modelId];
return archivePath;
}
It works fine as long as the App is running or coming back to live from the background mode. But once the app is terminated and re-run, the cached archive file is deleted.
Is there any way to persist the archive file so that I can load the cache stored last time when the app was launched.
I have already realised that each time the app is launched, the application id part of the NSHomeDirectory() is different. Does this have anything to do with my issue?
The issue is the "tmp" directory name at the top level. Generally files are saved under the "Documents" directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];`
Persistent caches are generally placed under the "Library" directly, use NSLibraryDirectory.
See: File System Programming Guide
tmp/
Use this directory to write temporary files that do not need to persist between launches of your app. Your app should remove files from this directory when they are no longer needed; however, the system may purge this directory when your app is not running.
I am working on a project where I need to manage videos. I need to rename or delete video. For that we need to hold the video in NSDATA and then manage it.
But I am getting an error message as Terminated due to memory error on below statement.
Edited
NSData *data=[NSData dataWithContentsOfFile:self.path];
if (data){
BOOL success = [data writeToFile:videopath atomically:NO];
}
self.path contains the path of video file. It works in small size video (of 4-10 mins) But it crashes in large size video (bigger than 20-30 mins).
Please advice.
Use this code instead loading the video file to memory, Your code will work with small files but u gonna fail with big files.
if ( [[NSFileManager defaultManager] isReadableFileAtPath:source] ){
[[NSFileManager defaultManager] copyItemAtURL:source toURL:destination error:nil];}
You are maintaing the full video as NSData inside the application. Instead of using a Video file as NSData, copy the video to some where (e.g NSTempoaryDirectoy). You can delete or rename the Old video.
I am not sure what the requirement for you. from your question I understood that you need to rename your video file. for renaming, why we need to go for reading it as NSdata and again writing the same. for Renaming try the below code.
NSFileManager *filemanager = [NSFileManager defaultManager];
if ([filemanager fileExistsAtPath:filePath])
{
NSString *target = [[filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newnameofthefile];
[filemanager moveItemAtPath:filePath toPath:target error:nil];
}
I hope this may help you..