CFURLSetResourcePropertyForKey failed when disable data backup on NSDocumentDirectory - ios

I am trying to download image files and store in NSDocumentDirectory. In order to do so, I has to turn off data backup on iCloud and iTunes. Below are my codes:
+(void)saveData:(NSData*)thedata:(NSString*)fileName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createFileAtPath:localFilePath contents:thedata attributes:nil];
//prevent files from backup on iCloud or iTune
NSURL *fileURL = [NSURL URLWithString:localFilePath];
[self addSkipBackupAttributeToItemAtURL:fileURL];
}
and for my addskipbackupattributetoitematurl:
+(BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)fileURL
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
{
NSLog(#"File %# doesn't exist!",[fileURL path]);
return NO;
}
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer isEqualToString:#"5.0.1"])
{
const char* filePath = [[fileURL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
NSLog(#"Excluded '%#' from backup",fileURL);
return result == 0;
}
else if (&NSURLIsExcludedFromBackupKey)
{
NSError *error = nil;
BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
if (result == NO)
{
NSLog(#"Error excluding '%#' from backup. Error: %#",fileURL, error);
return NO;
}
else
{
NSLog(#"Excluded '%#' from backup",fileURL);
return YES;
}
}
else
{
return YES;
}
}
However, the BOOL result = [fileURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error]; created the following message
CFURLSetResourcePropertyForKey failed because it was passed this URL which has no scheme: /var/mobile/Applications/CF69D567-1D37-4053-BFA8-5D0FCBD9C2B2/Documents/coffee.jpg
I'm just wondering if any encountered this problem??

Solved. once I changed
NSURL *fileURL = [NSURL URLWithString:localFilePath];
to
NSURL *fileURL = [NSURL fileURLWithPath:localFilePath];
everything work perfectly.

Swift:
let fileURL = URL(fileURLWithPath: somepath)

Related

What is the least resource-intensive way to know whether the object is a folder?

I need to sort 8145 objects (there may be more) for files and folders. (Tested on A8X).
First method.
for(NSString *filename in FilesList) //This method takes an average of 7.7 seconds.
{
fileExtension = (__bridge CFStringRef)[filename pathExtension];
fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);
if ([­[­[­[NSFileManager defaultManager] attributesOfItemAtPath:[FolderPath stringByAppendingPathComponent:filename] error:nil] fileType] isEqualToString:#"NSFileTypeDirectory"] && !UTTypeConformsTo(fileUTI, kUTTypeRTFD))
[OnlyFolderList addObject:filename];
else
[OnlyFilesList addObject:filename];
}
Second method.
for(NSString *filename in FilesList) //This method takes an average of 2.9 seconds.
{
fileExtension = (__bridge CFStringRef)[filename pathExtension];
fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);
[[NSFileManager defaultManager] fileExistsAtPath:[FolderPath stringByAppendingPathComponent:filename] isDirectory:&isDir];
if (isDir && !UTTypeConformsTo(fileUTI, kUTTypeRTFD))
[OnlyFolderList addObject:filename];
else
[OnlyFilesList addObject:filename];
}
Do you know a faster way?
-----Update with add fastest method----- // 0.26 seconds for 8145 objects!
NSNumber *isDirectory;
NSError *error = nil;
NSString *name;
NSArray *FilesList = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[NSURL fileURLWithPath:FolderPath] includingPropertiesForKeys:[NSArray arrayWithObjects:NSURLIsDirectoryKey,NSURLNameKey,nil] options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
for (NSURL *url in FilesList)
{
[url getResourceValue:&name forKey:NSURLNameKey error:&error];
[url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error];
if ([isDirectory boolValue])
{
CFStringRef fileExtension = (__bridge CFStringRef)[name pathExtension];
CFStringRef fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);
if (!UTTypeConformsTo(fileUTI, kUTTypeRTFD))
[OnlyFolderList addObject:name];
else
[OnlyFilesList addObject:name];
}
else
[OnlyFilesList addObject:name];
}
Try using contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error::
NSURL *root = ... // the root URL to get the file list from
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = nil;
NSArray *filesList = [fm contentsOfDirectoryAtURL:root includingPropertiesForKeys:#[ NSURLIsDirectoryKey, NSURLTypeIdentifierKey ] options:NSDirectoryEnumerationSkipsHiddenFiles error:&error];
if (dirURLs) {
for (NSURL *fileURL in filesList) {
NSString *filename = [[fileURL path] lastPathComponent];
NSNumber *isDir = nil;
[fileURL getResourceValue:&isDir forKey:NSURLIsDirectoryKey error:nil]
if ([isDir boolValue]) {
NSString *uti;
[fileURL getResourceValue:&uti forKey:NSURLTypeIdentifierKey error:nil];
if ([(__bridge NSString *)kUTTypeRTFD isEqualToString:uti]) {
[OnlyFilesList addObject:filename];
} else {
[OnlyFoldersList addObject:filename];
}
} else {
[OnlyFilesList addObject:filename];
}
}
} else {
NSLog(#"Unable to get list of files in %#: %#", root, error);
}
In the second method move fileExtension and fileUTI inside a test for isDir so that code does not run if the file is not potentially a directory.
Try this:
NSFileManager *fileManager = [NSFileManager defaultManager];
for(NSString *filename in FilesList) {
[fileManager fileExistsAtPath:[FolderPath stringByAppendingPathComponent:filename] isDirectory:&isDir];
if (isDir) {
CFStringRef fileExtension = (__bridge CFStringRef)[filename pathExtension];
CFStringRef fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);
if (!UTTypeConformsTo(fileUTI, kUTTypeRTFD))
[OnlyFolderList addObject:filename];
else
[OnlyFilesList addObject:filename];
}
else
[OnlyFilesList addObject:filename];
}
Try using the BSD API directly.
static BOOL cStringHasSuffix(const char *string, const char *suffix) {
unsigned long stringLength = strlen(string);
unsigned long suffixLength = strlen(suffix);
return stringLength >= suffixLength && memcmp(string + stringLength - suffixLength, suffix, suffixLength) == 0;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *url = [[NSBundle mainBundle] bundleURL];
NSMutableArray *folderNames = [NSMutableArray array];
NSMutableArray *fileNames = [NSMutableArray array];
const char *rtfdSuffix = ".rtfd";
DIR *dir = opendir(url.fileSystemRepresentation);
struct dirent *item;
while ((item = readdir(dir))) {
NSString *name = [NSString stringWithUTF8String:item->d_name];
if (item->d_type == 0) {
NSLog(#"unknown type for %#", name);
} else if (item->d_type == DT_DIR) {
if (cStringHasSuffix(item->d_name, rtfdSuffix)) {
[fileNames addObject:name];
} else {
[folderNames addObject:name];
}
} else if (item->d_type == DT_REG) {
[fileNames addObject:name];
} else {
NSLog(#"unexpected type %d for %#", item->d_type, name);
}
}
closedir(dir);
NSLog(#"fileNames = %#", fileNames);
NSLog(#"folderNames = %#", folderNames);
return YES;
}

ios - transfer In App Purchase downloaded file to Document folder

I successfully test my in app purchase function and downloaded the content. However I am not sure of an right way to transfer it to Document folder. I tested with the code:
-(void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
for (SKDownload *download in downloads)
{
switch (download.downloadState) {
case SKDownloadStateActive:
NSLog(#"Download progress = %f",
download.progress);
NSLog(#"Download time = %f",
download.timeRemaining);
break;
case SKDownloadStateFinished:
[self downloadFromURL:download.contentURL];///<--This is the function.
break;
}
}
}
-(void)downloadFromURL: (NSURL *) temporaryURL {
NSString *folderName = [[temporaryURL path] lastPathComponent];
NSArray *pathArr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *folder = [pathArr objectAtIndex:0];
NSString *filePath = [folder stringByAppendingPathComponent:folderName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSError *writeError = nil;
NSData *downloadData = [[NSData alloc] initWithContentsOfURL:temporaryURL];
[downloadData writeToURL: fileURL options:0 error:&writeError];
if( writeError) {
NSLog(#"Error in writing file %#' : \n %# ", filePath , writeError);
return;
}
NSLog(#"File successfully downloaded. Url is %#",fileURL.absoluteString);
//myFileURL = fileURL;
NSFileManager *filemgr;
NSArray *filelist;
int count;
int i;
filemgr =[NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:folder error:NULL];
count = [filelist count];
NSLog(#"file count %i",count);
for (i = 0; i < count; i++)
NSLog(#"%#", filelist[i]);
}
I get a #"File successfully downloaded. Url is %#" from the code above but NSLog(#"%#", filelist[i]); give me no content. What else is missing here? I found out about this link
but not sure how to incorporate into my code. Any pointer will be good.
Let's check:
-(void)downloadFromURL: (NSURL *) temporaryURL {
// at this time, file is downloaded successfully???
// I think you should check here
NSURL * temporaryURL;
NSFileManager *fm = [NSFileManager defaultManager];
BOOL existed = [fm fileExistsAtPath:temporaryURL.path];
if(existed) // file is existed
else // file is not existed == maybe download fails
}

Preventing files inside a folder to be backed up icloud

Thanks in advance for help.
I have excluded a folder from being backed up by iCloud but still it is backing up the files and when i visit iCould it is backed up. i use the following code to exclude the directory from being back up.
- (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;
}
and i call the above method as bellow
NSArray *Paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDir = [Paths objectAtIndex:0];
NSString *downloadFolder = [libraryDir stringByAppendingPathComponent:#"downloads"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:downloadFolder])
[[NSFileManager defaultManager] createDirectoryAtPath:downloadFolder withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
NSURL *documentURL = [NSURL URLWithString:downloadFolder];
[self addSkipBackupAttributeToItemAtURL:documentURL];
import this sys/xattr.h
- (BOOL) addSkipBackupAttributeToItemAtPath: (NSString *) path {
BOOL success = NO;
const char* filePath = [path fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
void* check = (void *)&NSURLIsExcludedFromBackupKey;
if (check != NULL) {
// First try and remove the extended attribute if it is present
int result = getxattr(filePath, attrName, NULL, sizeof(u_int8_t), 0, 0);
if (result != -1) {
// The attribute exists, we need to remove it
int removeResult = removexattr(filePath, attrName, 0);
if (removeResult == 0) {
NSLog(#"Removed extended attribute on item at path %#", path);
}
}
NSURL *url = [NSURL fileURLWithPath: path];
success = [url setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: nil];
} else {
// iOS 5.0.1 and lower
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
success = (result == 0);
}
NSLog(#"Add skip backup attribute for item at path: %#, result: %d", path, success);
return success;
}
i hope this will work...

App rejected due to downloading of image from server iOS

I have developed app in which i am downloading image from server and displaying in UITableView
App rejection reason
In particular, we found that on launch and/or content download, your app stores 2.67 MB. To check how much data your app is storing:
The iOS Data Storage Guidelines indicate that only content that the user creates using your app, e.g., documents, new files, edits, etc., should be backed up by iCloud.
Temporary files used by your app should only be stored in the /tmp directory; please remember to delete the files stored in this location when the user exits the app.
Data that can be recreated but must persist for proper functioning of your app - or because customers expect it to be available for offline use - should be marked with the "do not back up" attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCFURLIsExcludedFromBackupKey attribute.
Here is my code shows how i am downloading data from server and displaying it:
- (BOOL)fileExist:(NSString *)name //Check's whether image Exists in Doc Dir.
{
BOOL theSuccess;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
NSFileManager *fileManager = [NSFileManager defaultManager];
theSuccess = [fileManager fileExistsAtPath:fullPath];
if(theSuccess){
return YES;
} else {
return NO;
}
}
- (void)downloadFile:(NSString *)urlFile withName:(NSString *)fileName //If image not exists it will download image.
{
NSString *trimmedString = [urlFile stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([trimmedString length]>0)
{
HTTPEaterResponse *response = [HTTPEater get:[NSString stringWithFormat:#"%#",trimmedString]];
if ([response isSuccessful])
{
[self saveImage:[[UIImage alloc] initWithData:[response body]] withName:fileName];
}
}
}
-(void)saveImage:(UIImage *)image withName:(NSString *)name //After downloading image it stores in Doc dir.
{
NSString *pngPath = [NSHomeDirectory() stringByAppendingPathComponent:[#"Documents/" stringByAppendingString:name]];
[UIImagePNGRepresentation(image) writeToFile:pngPath atomically:YES];
}
- (UIImage *)loadImage:(NSString *)name //Used for displaying.
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:name];
UIImage *img = [UIImage imageWithContentsOfFile:fullPath];
return img;
}
Code for displaying data:
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
...
if ([dicImages valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]])
{
cell.MerchntLogo.image=[dicImages valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]];
}
else
{
if (!isDragging_msg && !isDecliring_msg)
{
if ([[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"] length]!=0)
{
[dicImages setObject:[UIImage imageNamed:#"rowDefault.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:#"merchantimage"]];
[self performSelectorInBackground:#selector(downloadImage_3:) withObject:indexPath];
}
}
else
{
cell.MerchntLogo.image=[UIImage imageNamed:#"rowDefault.png"];
}
}
...
}
-(void)downloadImage_3:(NSIndexPath *)path{
if ([[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"] length]!=0)
{
NSString *str=[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"];
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]];
[dicImages setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:#"merchantimage"]];
[tblProdDetail performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
}
}
Please help me figure out why my app has been rejected, and what I can do to rectify the problem.
Your app is clearly violating Apple's Data storage guidelines which states that only user-generated data should be stored in the Documents folder. This data is automatically backed up to iCloud and goes against the 5GB cap. If an app stores too much data in this folder (as deemed by Apple), then it can be rejected from the App Store.
Your data wont classify as user generated content and it exceeds 2 MB which is the limit.
You can prevent the data from being backed up by referring here.
https://developer.apple.com/library/ios/qa/qa1719/_index.html
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
BOOL result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result;
}
You need to do what they a talking about. Mark files
Just add in didFinishLaunching
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
[self applyAttributes:documentsDirectory];
And then implements this methods
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
-(void)applyAttributes:(NSString *)folderPath
{
NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
NSString *fileName;
while (fileName = [filesEnumerator nextObject]) {
// NSLog(#"apply to %#", [[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]] path]);
if([self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:[folderPath stringByAppendingPathComponent:fileName]]])
{
//NSLog(#"success applying");
}
//NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:fileName] error:nil];
//fileSize += [fileDictionary fileSize];
}
}
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
if([[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;
}
return NO;
}
Use this method to bypass storing data on iCloud
Pass file path to this method
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
BOOL result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result;
}

How to copy sqlite database when application is launched in iOS?

I want to copy my sqlite database from the database location with latest updates to my iOS application every time I launch the application.
Is there any way to do it?
you can add following methods to your appdelegate
- (void) copyDatabaseIfNeeded {
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
- (NSString *) getDBPath
{
//Search for standard documents using NSSearchPathForDirectoriesInDomains
//First Param = Searching the documents directory
//Second Param = Searching the Users directory and not the System
//Expand any tildes and identify home directories.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
//NSLog(#"dbpath : %#",documentsDir);
return [documentsDir stringByAppendingPathComponent:#"database.sqlite"];
}
and call this method in your did finish with launching method
[self copyDatabaseIfNeeded]; hope this will help.
use below code for coping database when application launch
in your appdelegate.m
in
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
[self getdatabase];
return YES;
}
and add below function in to your appdelegate.m
-(void)getdatabase
{
BOOL success;
NSFileManager *filemanager = [NSFileManager defaultManager];
NSError *error;
NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DBPath = [pathArray objectAtIndex:0];
NSString *writableDBPath = #"";
writableDBPath = [DBPath stringByAppendingPathComponent:#"xyz.sqlite"];
NSLog(#"writableDBPath:%#",writableDBPath);
success = [filemanager fileExistsAtPath:writableDBPath];
if (!success) {
NSString *defaultDBpath = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:#"xyz.sqlite"];
success = [filemanager copyItemAtPath:defaultDBpath toPath:writableDBPath error:&error];
if (!success) {
NSAssert(0, #"failed to copy database at path with message '%#'.",[error localizedDescription]);
}
}
NSLog(#"111writableDBPath:%#",writableDBPath);
}
Here it is in Swift 4/5
func copyDatabaseIfNeeded(sourcePath : String) -> Bool {
var destPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
destPath = destPath + "/foo.db3"
let databaseExistsWhereNeeded = FileManager.default.fileExists(atPath: destPath)
if (!databaseExistsWhereNeeded) {
do {
try FileManager.default.copyItem(atPath: sourcePath, toPath: destPath)
print("db copied")
}
catch {
print("error during file copy: \(error)")
}
}
return true
}
try this one:
NSArray *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *strDocDirectory = [docPath objectAtIndex:0];
self.strDatabasePath = [strDocDirectory stringByAppendingPathComponent:YOUR_DB];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: self.strDatabasePath ] == NO)
{
const char *dbpath = [self.strDatabasePath UTF8String];
sqlite3 *contactDB;
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS YOUR_Table (ID INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)";
if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(#"Failed to create table");
}
sqlite3_close(contactDB);
Try this in AppDelegate Class
.h file
#property(nonatomic, retain) NSString *dbPath;
.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self copyDatabaseIfNeeded];
}
- (void) copyDatabaseIfNeeded
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success)
{
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"sampleDB.sqlite3"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
/********* Database Path *********/
- (NSString *) getDBPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"sampleDB.sqlite3"];
}
It'll automatically copy, if it doesn't found any database in application.
Hopefully, it'll help you.
Thanks.
-(void)openDatase{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
self.databasePath = [documentsDirectory stringByAppendingPathComponent:#"weightCal.sqlite"];
if (sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSLog(#"Database Successfully Opened ");
} else {
NSLog(#"Error in opening database ");
}
}
-(void)dealloc{
sqlite3_close(database);
[super dealloc];
}
-(void)copyDatabase {
BOOL success;
NSFileManager *fileManager=[NSFileManager defaultManager];
NSError *error;
NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory=[paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:#"test.sqlite"];
success = [fileManager fileExistsAtPath:writablePath];
if(success) {
return;
}
NSString *defaultPath=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"test.sqlite"];
success=[fileManager copyItemAtPath:defaultPath toPath:writablePath error:&error];
if(!success){
NSAssert1(0,#"Failed to create writable database file with message '%#' .",[error localizedDescription]);
}
}
Declare following teo variable in .h:
sqlite3 *database;
NSString *databasePath;

Resources