In my app I want to copy a file from my bundle to documents directory in order to modify it.
Here's my code:
+(BOOL) copyDB: (NSString*) pdbName {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES) objectAtIndex: 0];
dbPath = [dbPath stringByAppendingPathComponent: #"myApp"];
dbPath = [dbPath stringByAppendingPathComponent: #"Profiles"];
dbPath = [dbPath stringByAppendingPathComponent: #"ES-EN"];
dbPath = [dbPath stringByAppendingPathExtension: #"prof"];
if([fileManager fileExistsAtPath: dbPath]) {
DebugLog(#"file exists at path %#", dbPath);
return FALSE;
}
NSString *defaultDBPath = [ [ [NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: #"ES-EN"];
defaultDBPath = [defaultDBPath stringByAppendingPathExtension: #"prof"];
DebugLog(#"dbPath: %#", dbPath);
DebugLog(#"defaultDBPath: %#", defaultDBPath);
if(![fileManager fileExistsAtPath: defaultDBPath]) {
DebugLog(#"Cannot find resource file");
return FALSE;
}
BOOL success = [fileManager copyItemAtPath: defaultDBPath toPath: dbPath error: &error];
if (!success) {
DebugLog(#"!success: Failed to create writable database file with message '%#'.", [error localizedDescription]);
UIAlertView *msg = [[UIAlertView alloc]
initWithTitle:#"Error"
message: [NSString stringWithFormat: #"Failed to create writable database file with message '%#'.", [error localizedDescription] ]
delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[msg show];
[msg release];
return FALSE;
}
[ [UserProfile sharedUserProfile] writeInitialData: pdbName];
//Creating fruits folder
NSString *dicDir = [Fruits_Dir stringByAppendingPathComponent: pdbName];
//Does a directory exist?
if ( ![fileManager fileExistsAtPath: dicDir] )
{
//Create a directory
DebugLog(#"Creating userName dir");
if (![fileManager createDirectoryAtPath: dicDir attributes:nil])
{
DebugLog(#"failed to create dicDir");
}
}
return TRUE;
}
I suppose that this code should work. Somehow it works as it should on the simulator, but it doesn't work on the device. I get a log that the resource file cannot be found.
What may be the problem?
Thanks.
One way that this can happen is for the resource file to have been accidentally removed as a reference from your XCode project.
If the file was once there then likely it has been installed into the simulator app directory. Even after removing it from XCode the file will stay there and your app will work in the simulator.
But as soon as you install it clean on the device the file will be missing.
Confirm that the file is listed in your XCode project resources and completely remove the app from the simulator and try it there again to get everything in sync.
Related
I am trying to upload audio file like session1.mp3 from document directory to iCloud using the following code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"session1.mp3"];
NSURL* sourceURL = [[NSURL alloc] initFileURLWithPath:path];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:path]) {
NSLog(#"File found!");
}
else
{
NSLog(#"File not found!");
}
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq)
{
NSLog(#"iCloud access at %#", ubiq);
NSError* error = nil;
NSURL *destinationURL = [[ubiq URLByAppendingPathComponent:#"Documents"] URLByAppendingPathComponent:#"session1.mp3"];
[[NSFileManager defaultManager] setUbiquitous:YES
itemAtURL:sourceURL
destinationURL:destinationURL
error:&error];
if(error != nil)
{
NSLog(#"Error while uploading the file: %#", error);
}
else
{
NSLog(#"File ulpoaded successfully");
}
}
else
{
NSLog(#"No iCloud access");
}
The file i am trying to upload exists (the "File found" is printed), but the uploading it to iCloud generates the following error
Error while uploading the file: Error Domain=NSCocoaErrorDomain Code=513 "The operation couldn’t be completed. (Cocoa error 513.)" UserInfo=0x1f03d9f0 {NSURL=file://localhost/var/mobile/Applications/20D82CDA-021E-4067-B9AB-C0197A6FA834/dox.app/session1.mp3, NSUnderlyingError=0x1f03d990 "The operation couldn’t be completed. Operation not permitted"}
Nothing inherently wrong with your code.
Are you checking the ubiquityIdentityToken anywhere to make sure it is available?
[ [ NSFileManager defaultManager ] ubiquityIdentityToken ];
Also, in your logging of a successful setUbiquitous, "upload successful" is not exact: the item was simply moved to the ubiquity container, and will be uploaded when the demon feels like it. You can check on the upload status through NSMetadataQuery.
You are not supposed to use iCloud to store this media.
Please review the Guidelines given by Apple.
My application just rejected because I copied sqlite database in NSDocumentDirectory and didn't exclude it from being synced to iCloud. I tried to add code to exclude it from iCloud but it is still occupying same space in iCloud. Here is my code.
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {
if (&NSURLIsExcludedFromBackupKey == nil) { // iOS <= 5.0.1
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
} else { // iOS >= 5.1
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
}
+ (void)copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSString *toPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:toPath];
if(!success) {
NSString *fromPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
NSURL *toURL = [NSURL fileURLWithPath:toPath];
NSURL *fromURL = [NSURL fileURLWithPath:fromPath];
[[NSFileManager defaultManager] addSkipBackupAttributeToItemAtURL:toURL];
[[NSFileManager defaultManager] addSkipBackupAttributeToItemAtURL:fromURL];
success = [fileManager copyItemAtURL:fromURL toURL:toURL error:&error];
if (!success)
NSLog(#"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
+ (NSString *)getDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:databaseName];
}
Please help.
You set the skip back attribute to the file before coping it, since the file is not yet copied there the filemanager can't change the properties of that file:
Also you are not calling the addSkipBackupAttributeToItemAtURL: on self but on NSFileManager which does have this method declared.
You can addSkipBackupAttributeToItemAtURL: from a class method if you declared it as an instance methods, change it to + to make it a class method.
Change it to something like:
+ (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {
if (&NSURLIsExcludedFromBackupKey == nil) { // iOS <= 5.0.1
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
} else { // iOS >= 5.1
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
}
+ (void)copyDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSString *toPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:toPath];
if(!success) {
NSString *fromPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
NSURL *toURL = [NSURL fileURLWithPath:toPath];
NSURL *fromURL = [NSURL fileURLWithPath:fromPath];
success = [fileManager copyItemAtURL:fromURL toURL:toURL error:&error];
if (success) {
[self addSkipBackupAttributeToItemAtURL:toURL];
} else {
NSLog(#"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
}
Also a my comment stated I removed the [[NSFileManager defaultManager] addSkipBackupAttributeToItemAtURL:fromURL]; since that file will a not be included in an iCloud backup and b files in the bundle are readonly and can't there for be modified.
I was on the phone with an Apple support guy about this.
However, rather than repeating stuff, this answer covers it well: Setting NSDocumentDirectory so it doesn't backup to iCloud
Please refer to Technical Q&A QA1719 which describes that the technique you employ in addSkipBackupAttributeToItemAtURL is advised for iOS 5.0.1 and earlier. For iOS 5.1 and later, you should use the following:
- (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;
}
NSDocumentDirectory has nothing to do with iCloud. the documents directory for an iOS application is NOT automatically backed up to iCloud at all. Its the same as it ever was, just a sandbox directory for your app.
You only store things in iCloud if the following conditions are met:
Your app has entitlements specifying iCloud sandbox container name
Your user is logged into iCloud on their device
You explicitly get the ubiquity container's documents directory and store things there.
So if you dont want to store something in iCloud, dont get the documents directory for the ubiquity container, dont connect to iCloud at all...
Also the iCloud backup is not even an application level setting the user sets it, so I dont know why yo u even have iCloud enabled. Just put your data in the data directory and apple will have no problem with it.
Sqlite3 database is not connected in iPhone 4 running iOS 5.0.1, on both Wi-Fi and cellular networks. My apps 4 times rejected in Itunes Apple store due to this reason.
I am using XCode 3.2.4 using iPhone 3.2 iOS 4.1. where this app running well.
I write this codes-
/// # AppDelegate.m file
-(void)createDatabaseIfNeeded {
BOOL success;
NSError *error;
//FileManager - Object allows easy access to the File System.
NSFileManager *FileManager = [NSFileManager defaultManager];
//Get the complete users document directory path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//Get the first path in the array.
NSString *documentsDirectory = [paths objectAtIndex:0];
//Create the complete path to the database file.
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:#"passmanager.sqlite"];
//Check if the file exists or not.
success = [FileManager fileExistsAtPath:databasePath];
//If the database is present then quit.
if(success) return;
//the database does not exists, so we will copy it to the users document directory]
NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"passmanager.sqlite"];
//Copy the database file to the users document directory.
success = [FileManager copyItemAtPath:dbPath toPath:databasePath error:&error];
//If the above operation is not a success then display a message.
//Error message can be seen in the debugger's console window.
if(!success)
NSAssert1(0, #"Failed to copy the database. Error: %#.", [error localizedDescription]);
}
-(void)applicationDidFinishLaunching:(UIApplication *)application{
// createDatabaseIfNeeded method for first time to create database in new iPhone
[self createDatabaseIfNeeded];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
}
And Error gives accroding to Apple in the code in Some ViewController page
// # viewController.m
sqlite3 *database;
int result = sqlite3_open("passmanager.sqlite", &database);
if(result != SQLITE_OK){
sqlite3_close(database);
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:#"Database Connected"
message:#"No"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
else{
// some stuff
}
Every time Apple complained that if Condition is true as "Database Connected No"
While In my system else part is executing.
Please help me. Thax in advanced.
It looks like the path of the database you are trying to open is incomplete, it should be
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:#"passmanager.sqlite"];
int result = sqlite3_open([databasePath UTF8String], &database);
as that is what you set in createDatabaseIfNeeded
I have some code that copies all the directories from "/Documents" to "Library/Caches/". The code is as follows:
NSString *oldPath = [NSString stringWithFormat:#"%#/Documents/", NSHomeDirectory()];
NSString *newPath = [NSMutableString stringWithFormat:#"%#/Library/Caches/", NSHomeDirectory()];
NSError *error = nil;
// get the list of all files and directories
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *fileList = [fileManager contentsOfDirectoryAtPath:oldPath error:&error];
if(error != nil)
{
NSLog(#"\n\n\n1. There was an error in the file operation: %#", [error localizedDescription]);
return;
}
for(NSString *file in fileList)
{
NSString *path = [oldPath stringByAppendingPathComponent:file];
NSLog(#"The path for the file is: %#", path);
BOOL isDir = NO;
BOOL dirExists = [fileManager fileExistsAtPath:path isDirectory:(&isDir)];
if(isDir && dirExists)
{
//Move to the new location
[fileManager copyItemAtPath:path toPath:[newPath stringByAppendingPathComponent:file] error:&error];
if(error != nil)
{
NSLog(#"\n\n\n2. There was an error in the file operation: %#", [error localizedDescription]);
}
else
{
[fileManager removeItemAtPath:path error:&error];
if(error != nil)
NSLog(#"\n\n\n3. There was an error in the file operation: %#", [error localizedDescription]);
}
}
}
The copy works fine. I can see all the directories copied to the new location.
The problem is that the empty directories still remain in the Documents folder. I read up on removeItemAtPath in the docs and it says there that the contents of the directory are deleted. Whether the actual directory itself is deleted or not has no mention.
Could someone tell me what could be going wrong in the code? Why do the empty directories still remain?
EDIT:
On the first pass, when the directories exist in Documents, but not in Library/Caches, removeItemAtPath does not throw an error. The empty directories still remain in Documents, though. On the second pass of the above code, it attempts to remove the empty directories and removeItemAtPath throws a cocoa error 516 which is basically file not found - this is weird, because I can still see those empty directories.
Also, I'm running this code on iPhone Simulator 4.3.2 and iPhone Simulator 5.0, and monitoring the directory structure on my Mac in /Users/Library/Application Support/iPhone Simulator/....
This may be happening because of the trailing "/" in "/Documents/". Try removing the trailing "/" from the first 2 lines, or use this:
NSString *oldPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *newPath = [NSString pathWithComponents:[NSArray arrayWithObjects:NSHomeDirectory() , #"Library", #"Caches", nil]];
NSError *error = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *fileList = [fileManager contentsOfDirectoryAtPath:oldPath error:&error];
if (error) {
NSLog(#"\n\n\n1. There was an error in the file operation: %#", [error localizedDescription]);
return;
}
for (NSString *file in fileList) {
NSString *path = [oldPath stringByAppendingPathComponent:file];
NSLog(#"The path for the file is: %#", path);
BOOL isDir = NO;
if ([fileManager fileExistsAtPath:path isDirectory:&isDir] && isDir) {
[fileManager copyItemAtPath:path toPath:[newPath stringByAppendingPathComponent:file] error:&error];
if(error) {
NSLog(#"\n\n\n2. There was an error in the file operation: %#", [error localizedDescription]);
} else {
[fileManager removeItemAtPath:path error:&error];
if (error) {
NSLog(#"\n\n\n3. There was an error in the file operation: %#", [error localizedDescription]);
}
}
}
}
I have created a folder within the Documents folder in my application directory .
I wanted to rename that folder through code,but not able to understand how to do it.
Please help me out.
Have you tried?
NString *newDirectoryName = #"<new folder name>";
NSString *oldPath = #"<path to the old folder>";
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newDirectoryName];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:&error];
if (error) {
NSLog(#"%#",error.localizedDescription);
// handle error
}
NSString *oldDirectoryPath = #"Type your old directory Path";
NSArray *tempArrayForContentsOfDirectory =[[NSFileManager defaultManager] contentsOfDirectoryAtPath:oldDirectoryPath error:nil];
NSString *newDirectoryPath = [[oldDirectoryPath stringByDeletingLastPathComponent]stringByAppendingPathComponent:newDirectoryname];
[[NSFileManager defaultManager] createDirectoryAtPath:newDirectoryPath attributes:nil];
for (int i = 0; i < [tempArrayForContentsOfDirectory count]; i++)
{
NSString *newFilePath = [newDirectoryPath stringByAppendingPathComponent:[tempArrayForContentsOfDirectory objectAtIndex:i]];
NSString *oldFilePath = [oldDirectoryPath stringByAppendingPathComponent:[tempArrayForContentsOfDirectory objectAtIndex:i]];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:oldFilePath toPath:newFilePath error:&error];
if (error) {
// handle error
}
}
Using moveItemAtPath should work. Sometimes the directory isn't actually "renamed" but really moved to another place. In which case the target path directory structure needs to be created as well.
Here a code snippet i'm using that works well :
-(BOOL)renameDir:(NSString *)dirPath asDir:(NSString *)newDirPath cleanExisting:(BOOL)clean
{
NSError *error = nil;
NSFileManager *fm = [NSFileManager defaultManager];
if (clean && [fm fileExistsAtPath:newDirPath])
{
[fm removeItemAtPath:newDirPath error:&error];
if (error != nil)
{
NSLog(#"Error while renameDir %# as %# :\n%#",dirPath,newDirPath,error);
return NO;
}
}
//Make sure container directories exist
NSString *newDirContainer = [newDirPath stringByDeletingLastPathComponent];
if (![fm fileExistsAtPath:newDirContainer])
{
[fm createDirectoryAtPath:newDirContainer withIntermediateDirectories:YES attributes:nil error:&error];
}
if (error==nil)
{
[fm moveItemAtPath:dirPath toPath:newDirPath error:&error];
}
if (error!=nil)
{
NSLog(#"error while moveItemAtPath : %#",error);
}
return (error==nil);
}
This always work
NSLog (#"Copying download file from %# to %#", aPath, bPath);
if ([[NSFileManager defaultManager] fileExistsAtPath: bPath]) {
[[NSFileManager defaultManager] removeItemAtPath: bPath
error: &error];
}
if (![[NSFileManager defaultManager] copyItemAtPath: aPath
toPath: bPath
error: &error]){}
if ([[NSFileManager defaultManager] removeItemAtPath: aPath
error: &error]) {}
This is good article for renaming, deleting and create files.
// For error information
NSError *error;
// Create file manager
NSFileManager *fileMgr = [NSFileManager defaultManager];
// Point to Document directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
// Rename the file, by moving the file
NSString *filePath2 = [documentsDirectory stringByAppendingPathComponent:#"file2.txt"];
// Attempt the move
if ([fileMgr moveItemAtPath:filePath toPath:filePath2 error:&error] != YES)
NSLog(#"Unable to move file: %#", [error localizedDescription]);
// Show contents of Documents directory
NSLog(#"Documents directory: %#",
[fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
http://iosdevelopertips.com/data-file-management/iphone-file-system-creating-renaming-and-deleting-files.html