How to overwrite a folder using [NSFileManager defaultManager] when copying? - ios

Using the line below,
[fileManager copyItemAtPath:sourcePath toPath:targetPath error:&error];
We can copy a folder but if the folder already exists it throws an exception "File Exists".
In order to overwrite a single file, we can achieve it through the following lines:
NSData *myData = [NSData dataWithContentsOfURL:FileURL]; /fetch single file
[myData writeToFile:targetPath atomically:YES];
But I want to copy an already existing folder i.e, overwrite.
Edit :
Simple Possibility , I can remove the items before copying them.
Please suggest any more possibilities.

The default behavior of NSFileManager method is to throw an exception/error "File Exists." when the file exists. But still if you want to overwrite using NSFileManager then it provides one api for that which is mentioned below replaceItemAtURL as well in first solution:-
Also there are three solutions to achieve that
First Solution
[filemanger replaceItemAtURL:url1
withItemAtURL:url2
backupItemName:#"/Users/XYZ/Desktop/test.xml"
options:NSFileManagerItemReplacementUsingNewMetadataOnly
resultingItemURL:nil error:nil];
Using the above API you can overwrite the file contents. But before that you have to take the backup of your source path in your temporary directory.
Second Solution
Already you have mentioned in your question using NSData writeToUrl.
Third Solution
trojanfoe has mentioned in their answer. i.e. remove the item being overwritten beforehand.

I would like to add one more using delegate, in order to override files with copyItemAtPath (NSFileManager) function use:
[[NSFileManager defaultManager] setDelegate:self];
[[NSFileManager defaultManager] copyItemAtPath:fileOrigin toPath:fileDestin error:&error];
and implement the delegates optional function:
- (BOOL)fileManager:(NSFileManager *)fileManager shouldProceedAfterError:(NSError *)error copyingItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath{
if ([error code] == NSFileWriteFileExistsError) //error code for: The operation couldn’t be completed. File exists
return YES;
else
return NO;
}

Remove the item first, with:
[fileManager removeItemAtPath:targetPath error:NULL];
(i.e. ignoring any error)

if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];

Related

EXC_BAD_ACCESS Exception while copy item to path iOS

I'm trying to copy an item from orginal path for destination path, but it throw exception while copying file. Any body can examine why? Thank in advance.
- (void) copyFile:(NSString*) fromPath toPath:(NSString*) toPath
{
NSError *error = nil;
NSFileManager* fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath:toPath];
if (success)
[fileManager removeItemAtPath:toPath error:&error];
success = [fileManager copyItemAtPath:fromPath toPath:toPath error:&error];
if (!success) {
NSLog(#"fail to copy signature temp file!");
}
}
I receive no error logs!
I have seen this error several times in relation to delegates.
Have you set the file manager's delegate? If you have be sure that the delegate is still valid when that method is executed. Add a log statement to be sure.
If you haven't set one it might be worth setting one just to see if that has an effect.

iOS Data Storage Rejection

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];
}

delete files from database permanently ios

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];
}

Providing Initial Data with Core Data in iOS

Here's what I need: To have a sqlite file populated with example entities that I made on the iPhone simulator, and then copy that file when the app initially runs for all my users.
What I've done:
I created a bunch of entries within the simulator.
I found the sqlite file attached to my app within the iPhone Simulator iOS folder on the MAC.
From the three files, .sqlite, .sqlite-shm, .sqlite-wal I simply copied the .sqlite file to my xCode project.
When I ran the app, the .sqlite file showed up empty!
How do I fix this?
Thank you!
EDIT:
What significance does the .sqlite-wal and .sqlite-shm have?
Why do they exist and why did not exist prior to iOS7?
first steps R OK but then U have to load the database
U need smth like this:
- (void)copyPreparedDatabase{
__persistentStoreCoordinator = nil;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"DATABASE.sqlite"];
NSString *storePath = [storeURL path];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"DATABASE" ofType:#"sqlite"];
if (defaultStorePath) {
NSError *error = nil;
if ([fileManager fileExistsAtPath:storePath]) {
[fileManager removeItemAtPath:storePath error:&error];
}
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:&error];
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storePath error:&error]) {
}
}
}
And then U call it from - (NSPersistentStoreCoordinator *)persistentStoreCoordinator from
AppDelelate.m
Advice: Do some custom switch like
#define IMPORT_PREPARED_DATABASE
do it like this:
if (![fileManager fileExistsAtPath:storePath] && !IMPORT_PREPARED_DATABASE) { //&& 1==2
[self copyPreparedDatabase];
}
so U can control when to build new prepared database or when to use existing one....
Note:
When U build new prepared database sto simulator, copy database and paste it over the old one...
This tutorial can be a big help.
You made almost everything, but you are missing an important step. You need to copy the sqlite to your xcode project then you need to check in your persistentStoreCoordinator if the sqlite file exists in your Documents area. If not, you need to copy it. Jump to "Doctor, you’re needed in Xcode" section in that tutorial :).

download file to Documents directory

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/

Resources