I am Making an Audio recorder(m4a extension files). I am Giving a particular URL for the output of the recorded File(in directory).
I am able to play it, save the path of the file in database and can retrieve it later. EVery thing is going Fine. BUT I am not able to delete the saved/unsaved files. Every time I record an audio , the file is taking a permanent space. Am not able to delete them.
I tried it over internet(stackoverflow ofcourse). I got Links like this: I have video URL and want to delete it from the iPhone using this URl
But they are showing COCOA ERROR 4 when ever i try to delete them using codes like this: [[NSFileManager defaultManager] removeItemAtPath:strPath error:&error];
Please suggest, and reply
You typically accomplish this for resources you've saved in your Apps documents directory like this:
unlink([pathForURL UTF8String]);
where pathForURL is an NSString that describes the path to the resource you're deleting.
This is the path earlier i was getting , at which i was unable to write file
/var/mobile/Applications/8584F54E-75D2-4833-8826-29C125E53DBC/Library/Documentation/291013193758w.png
This morning, I just run my code once again ,. now its showing path
/var/mobile/Applications/DDA14123-6A88-4756-B2E4-C4A3AA39AA5B/Documents/291013081335test.png
on this path am able to write my file
the Difference between two paths is that, first one is of Library/Documentation , where as second one is of Documents
dont know the difference, but it is working now
There may be case that file path which you provide is not correct. If its correct then try following with URL, it might solve your issue
NSString *str= [outputFieldURL absoluteString];
NSError *error;
NSURL *url = [NSURL URLWithString:str];
BOOL success = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (!success) {
NSLog(#"Error removing file at path: %#", error.localizedDescription);
}
else
{
NSLog(#"File removed at path: %#", error.localizedDescription);
}
}
Before deleting the file you have to check file there or not :
NSFileManager* manager = [[NSFileManager alloc] init];
if ([manager fileExistsAtPath:path]) {
[manager removeItemAtPath:path error:&error];
}
Related
Is there a way to detect if a file located on iCloudDrive has been moved to the iCloudDrive trash?
I could check the URL to contain ".Trash" but I am looking for an official way to retrieve this.
To detect if a file/folder is in Trash use following code:
NSURLRelationship relationship;
NSError *error;
[[NSFileManager defaultManager] getRelationship:&relationship ofDirectory:NSTrashDirectory inDomain:0 toItemAtURL:URL error:&error];
if (relationship == NSURLRelationshipContains) {
//file is in trash
}
Found a decent way to detect this. Starting with iOS11 the following approach is possible:
NSURL* fileURL; // any file URL pointing to a file resource
NSURL* trashURL = [NSFileManager.defaultManager URLForDirectory:NSTrashDirectory inDomain:NSUserDomainMask appropriateForURL: fileURL create:NO error:NULL];
if (trashURL && [fileURL.path hasPrefix:trashURL.path])
{
// fileURL is located in the iCloudDrive trash
}
My app got rejected because Apple found that on launch and/or content download, my app stores 14.18 MB.
Now I'm trying to skip backup of all the images and sounds I use in the game.
So far, I made a folder called "Resources" in my app folder itself, looking like this: App Folder Scrshot
What I did in AppDelegate.m is next:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self addSkipBackupAttributeToItemAtURL:[self applicationDocumentsDirectory]];
return YES;
}
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
NSError *error = nil;
BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
NSLog(#"Error excluding %# from backup %#", [URL lastPathComponent], error);
}
return success;
}
This isn't working.
I have 2 questions:
1)Am I doing the right thing from the start? Should I put all the images and sounds in folder called Resources, and then skipBackup for the entire folder or should I put them somewhere else?
If yes, then where?
(I saw over internet people talking about "Documents" folder...but I don't know what that folder is nor where to find it.
2)If I could put everything in "Resources" folder, how to I reach that folder from the code? How do I make URL to that folder, from Xcode itself?
Thanks in advance
You should deliver the content with your app. downloading the content on first launch is not a good idea due to the connection issue if user is on 3G/Edge.
the document directory is on the device, a folder under your app, and its created by ios automatically. Apple Documentation
getting files from resource folder is easy files from resources
I had this problem before ! The problem is not the size of what you store, it is where you store it. My guess is that you store your file in NSDocumentDirectory, which is bad because this directory should only be used to store data that the user created himself (documents, photo, etc). Adding the NSURLIsExcludedFromBackupKey is not enough. When it happened to me, I changed NSDocumentDirectory to NSApplicationSupportDirectory and my app got approved.
UPDATE
It is best if you first create a subdirectory in your NSApplicationSupportDirectory to store your file there.
Your methods should look like something like :
- (NSURL *) applicationDocumentsDirectory{
NSString *appSupportDir = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject];
appSupportDir = [appSupportDir stringByAppendingPathComponent:#"MyAppDirectory"];
return [NSURL URLWithString:appSupportDir];
}
And don't forget to create the directory first :
if (![[NSFileManager defaultManager] fileExistsAtPath:[self applicationDocumentsDirectory] isDirectory:NULL]) {
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:[self applicationDocumentsDirectory] withIntermediateDirectories:YES attributes:nil error:&error];
}
I want to start off by saying that this block of code worked before the implementation and roll out of iOS 7.
Basically I have a file name that I'm looking for in the NSCachesDirectory, so I create a URL object as my search item. Then I enumerate the directories (using the same NSFileManager object) and look for file names that equal each other, and that's how I know the file exists.
+ (BOOL)itemExistsInMemory:(NSString *)itemName
{
BOOL itemExists = NO;
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSArray *mySandboxDirs = [fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask];//get the directories for the application
NSURL *searchForURL = [[mySandboxDirs lastObject] URLByAppendingPathComponent:[NSString stringWithFormat:#"%#%#", itemName, FileNameAppendix]];//look for the specific file
NSArray *enumerator = [fileManager contentsOfDirectoryAtURL:[mySandboxDirs lastObject] includingPropertiesForKeys:[NSArray arrayWithObjects:NSURLNameKey, NSURLIsRegularFileKey, NSURLCreationDateKey, nil] options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
for(NSURL *url in enumerator)
{//find out if any of the URLs within the NSCachesDirectory match what we're looking for
NSNumber *isRegularFile = nil;
[url getResourceValue:&isRegularFile forKey:NSURLIsRegularFileKey error:NULL];
if([isRegularFile boolValue])
{
if([url relativeString] isEqualToString:[searchForURL relativeString]])
{
itemExists = YES;
break;
}
}
}
return itemExists;
}
The file DOES INDEED EXIST in the NSCachesDirectory, however, the code doesn't find it because the searchForURL object was created without a path component (the path component is private/...). Why? Even stranger is that I save the data to a URL that's created with the
[[mySandboxDirs lastObject] URLByAppendingPathComponent:[NSString stringWithFormat:#"%#%#", itemName, FileNameAppendix]];
instruction! So it doesn't include the private/ path component in the URL, but when I write the data with [NSData writeToURL:] it "redirects" it to the private/ directory.
So why can't [NSFileManager URLsForDirectory: inDomains:] get me the correct directories for NSCachesDirectory?
More info moved from the comment for better formatting:
By the way, here's an example of what's contained in the URLs I'm creating and looking for ->
When I create a URL for saving:
file:///var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Caches/Experimental%20Post.cnt
When I create a URL for searching:
file:///var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Caches/Experimental%20Post.cnt
What the enumerator sees:
file:///private/var/mobile/Applications/C63B378E-5EBE-417C-A465-8C3A3DCE013A/Library/Caches/Experimental%20Post.cnt
I could simply take the URLs that the enumerator comes up with and remove the "private" part of the URL so that the strings match and I can proceed, but I'd like to understand why this is happening. Please also note that this only happens when you put the app on an iDevice since the directories are different than when you simulate it with the iOS Simulator.
Thanks to anyone that can be of assistance.
/var is a symlink to /var/private, use [NSURL URLByResolvingSymlinksInPath] to resolve the symlink.
In your example:
for(NSURL *url in enumerator) {
NSURL *resolvedSymlinksURL = [url URLByResolvingSymlinksInPath];
...
}
More detailled discussion: What does the /private prefix on an iOS file path indicate?
in the for loop, see if the url object have some return characters (like \r or \n) and remove it before proceeding.
I'm trying to copy a downloaded file to a specific folder in the app's documents directory but can't seem to get it working. The code I'm using is:
NSString *itemPathString = #"http://pathToFolder/folder/myFile.doc";
NSURL *myUrl = [NSURL URLWithString:itemPathString];
NSArray *paths = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *folderPath = [[paths objectAtIndex:0] URLByAppendingPathComponent:#"folder"];
NSURL *itemURL = [documentsPath URLByAppendingPathComponent:#"myFile.doc"];
// copy to documents directory asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *theFM = [[NSFileManager alloc] init];
NSError *error;
[theFM copyItemAtURL:myUrl toURL:itemURL error:&error];
}
});
I can retrieve the file OK but can't copy it. Can anyone tell me if there's anything wrong with the above code?
If downloading a file from a server, if it's a reasonably small file (e.g. measured in kb, not mb), you can use dataWithContentsOfURL. You can use that method to load the file into memory, and then use the NSData instance method writeToFile to save the file.
But, if it's a larger file, you will want to use NSURLConnection, which doesn't try to hold the whole file in memory, but rather writes it to the file system when appropriate. The trick here, though, is if you want to download multiple files, you either have to download them sequentially, or encapsulate the NSURLConnection and the NSOutputStream such that you can have separate copies of those for each simultaneous download.
I have uploaded a project, Download Manager that demonstrates what a NSURLConnection implementation might look like, but it's non-trivial. You might rather want to contemplate using an established, third-party library, such as ASIHTTPRequest or RestKit.
If you want to access a folder with a given name you should check if it exists and if not create it. That could quite easy be done like this:
NSString *folder = [documentsPath stringByAppendingPathComponent:folderName];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
if (![fileManager fileExistsAtPath:folder]) {
[fileManager createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:&error];
}
if (error != nil) {
NSLog(#"Some error: %#", error);
return;
}
EDIT
If you want to check if the folder was created properly on your device got to Organizer -> Devices -> [YourDevelopingDeviceWhereTheAppWasInstalled] -> Applications -> [YourApplication]
In the lower section you should at least see some folders like Documents. And if successful your created folders as well.
You need to create any intermediate directories prior to copying files. Check in the Simulator folder to see wether the "folder" directory is created in the applications Documents-folder.
Path to simulator is /Users/$username/Library/Application Support/iPhone Simulator/
I'm developing an iPad App & currently testing it on the device itself - I'm using an sqlite database to read in the urls of .m4v movie files.
For testing using the simulator I list urls in the database as follows:
/Users/Octave1/Desktop/iDev/Moodymann/IMM Simulator App/Content/Movies/visuals seg0.m4v
.
.
.
This works fine & the database is read correctly, & the files play as required.
When I run the App on the iPad I change the urls in the database to the following format:
/Content/Movies/visuals seg0.m4v
.
.
.
However the movie doesn't play at all. It seems like there is a problem with the path & that the files aren't being found - anyone know the correct way to reference files within the Application itself?
Thanks in advance :)
I figured this out, for anyone with the same issue.
First of all - I copied my "Content" folder over to the iPad, placing it in the Library Directory, as follows:
//Finding out where the Library Directory is located
NSString *libraryDirectory = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//Find where my content folder is initially
NSString *contentPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Content"];
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtPath:contentPath
toPath:libraryDirectory
error:&error];
if([[NSFileManager defaultManager] copyItemAtPath:contentPath toPath:folderPath error:&error]){
NSLog(#"File successfully copied");
} else {
NSLog(#"Error description-%# \n", [error localizedDescription]);
NSLog(#"Error reason-%#", [error localizedFailureReason]);
}
I can then read out the address of each movie, & append each address to the address of the libarary
NSString *inFilePath = movieObj.pathToMovie; ///Content/Movies/visuals seg0.m4v from above
NSLog(#"inFilePath is: %#", inFilePath);
NSString *fullPath = [libraryDir stringByAppendingPathComponent:[[NSString alloc] initWithString:inFilePath]];
NSLog(#"fullPath is: %#", fullPath);
NSURL *url = [[NSURL alloc] initFileURLWithPath:fullPath];
NSLog(#"url is: %#", url);
[movieUrlArray addObject:url];
Now I know the urls of the movie files, within the Application's file system.