How to get SQLITE database file to sync in DropBox? - iphone

I am working on an IPad app.Here I want to upload whole database file to dropbox.I searched on google by but didnot found appropriate solution.I used the following code to create database.
-(BOOL) createDatabaseFile
{
NSString *docsDir;
NSArray *dirPaths;
NSFileManager *filemgr = [NSFileManager defaultManager];
BOOL successMsg = YES;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
// Build the path to the database file
self.detaildatabasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:#`"Database.sql"`]];
// Check For Existence of the database file
if ([filemgr fileExistsAtPath:self.detaildatabasePath])
{
//File Exists At The Path
}
else
{
//Since file is not available at the path create a Database File
successMsg = [filemgr createFileAtPath:self.detaildatabasePath contents:[NSData data] attributes:nil];
}
return successMsg;
}
So how can I get my "Database.sql" file.Please dont treat it as duplicate question.I had wasted a day for googling but didnot find solution..Please guide me.
Thanks in advance

To upload file to Dropbox you need Dropbox SDKs - https://www.dropbox.com/developers/sync/sdks/ios (how to add Dropbox.framework to your project)
Then you can upload file:
-(void) createBackupInDropbox {
NSString *filename = #"backup.sqlite"; //File name in DropBox
NSString *destDir = #"/backups"; //Destination path in DropBox
NSString *fromPath = #"..."; //local path to your DB file
/*
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
fromPath = [docsPath stringByAppendingPathComponent:#"my_database.sqlite"];
*/
[[self restClient] deletePath:[NSString stringWithFormat:#"%#/%#", destDir, filename]]; //delete file if you need to replace it
[[self restClient] uploadFile:filename toPath:destDir
withParentRev:nil fromPath:fromPath];
}
To control uploading process:
- (void)restClient:(DBRestClient*)client uploadedFile:(NSString*)destPath
from:(NSString*)srcPath metadata:(DBMetadata*)metadata {
NSLog(#"File uploaded successfully to path: %#", metadata.path);
}
- (void)restClient:(DBRestClient*)client uploadFileFailedWithError:(NSError*)error {
[waitIndicator dismissWithClickedButtonIndex:0 animated:YES];
NSLog(#"File upload failed with error - %#", error);
}
- (void)restClient:(DBRestClient*)client uploadProgress:(CGFloat)progress forFile:(NSString *)destPath from:(NSString *)srcPath
{
}
And restClient method:
- (DBRestClient *)restClient {
if (!restClient) {
restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
}
return restClient;
}

Related

DropboxSDK: error making request to /1/metadata/sandbox - (401) No auth method found. Can we trace this error using any dropbox delegate?

Using below code to upload file to dropbox, only change i made is to replace the file on dropbox server. But since then faced this problem for the first time got this warning in console only and not traceable in code but when user tries again it works. Can anyone guide why this happens?
-(void)uploadToDropbox
{
NSLog(#"Upload to dropbox from local DB");
if ([[DBSession sharedSession] isLinked])
{
StartLoadingIndicator:self];
[self addLoadingView];
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localPath=[documentsDirectory stringByAppendingPathComponent:#"/MyApp/MyApp.sqlite"];
success =[fileManager fileExistsAtPath:localPath];
if (success)
{
NSLog(#"DBX_Path %#",[NSString stringWithFormat:#"%#",[[NSUserDefaults standardUserDefaults] valueForKey:#"DBX_Path"]]);
}
else
{
NSLog(#"Not exist");
}
}
else
{
UIAlertView *Sessionalert=[[UIAlertView alloc]initWithTitle:#"You need to login first with valid credentials." message:nil delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[Sessionalert show];
Sessionalert=nil;
}
}
- (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata
{
NSLog(#"metadata:%#", metadata);
NSEnumerator *e= [metadata.contents objectEnumerator];
DBMetadata *dbObject;
//NSUInteger numberOfFiles = [metadata.contents count];
while ((dbObject = [e nextObject])) {
if (!dbObject.isDirectory) {
NSString *fileName = [dbObject.path lastPathComponent];
if (![fileName isEqualToString:#"MyApp.sqlite"]) {
/* call dbupload if dbObject.lastModifiedDate > than your local file*/
revName = nil;
}
else{
revName = [dbObject.rev lastPathComponent];
NSLog(#"revName:%#", revName);
}
}
}
NSString *filename = #"MyApp.sqlite";
NSString *destDir = #"/";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localPath=[documentsDirectory stringByAppendingPathComponent:#"/MyApp/MyApp.sqlite"];
[[self restClient] uploadFile:filename toPath:destDir
withParentRev:revName fromPath:localPath];
}
Please guide why this happens and what's the reason behind this? Can this be traceable via any delegate method.
Finally i got..
- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error {
NSLog(#"Error loading metadata: %#", error);
}
Got help from enter link description here

Can't copy database file using copyItemAtPath with cocoa error 4

I want to copy the database file from bundle to user document.
My code is below:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *userPath = [documentsDir stringByAppendingPathComponent:#"db.sql"];
NSString *srcPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"db.sql"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(#"Bundle database exists: %i",[fileManager fileExistsAtPath:srcPath]);
NSLog(#"User Document folder database exists: %i",[fileManager fileExistsAtPath:userPath]);
BOOL find = [fileManager fileExistsAtPath:userPath];
BOOL copySuccess = FALSE;
NSError *error;
if (!find) {
NSLog(#"don't have writable copy, need to create one");
copySuccess = [fileManager copyItemAtPath:srcPath toPath:userPath error:&error];
}
if (!copySuccess) {
NSLog(#"Failed with message: '%#'.",[error localizedDescription]);
}
and the result is always saying:
Bundle database exists: 1 User Document folder database exists: 0
don't have writable copy, need to create one Failed with message: 'The
operation couldn’t be completed. (Cocoa error 4.)'.
Please suggest, thanks.
Your code for determining your user's Documents Directory is incorrect.
Using your code, I put together a quick and dirty sample that works. For your application, you probably want to create some utils class that contains the static function 'applicationDocumentsDirectory' so that other classes in your project can call it, if needed.
Header File:
#import <UIKit/UIKit.h>
#interface TST_ViewController : UIViewController
+ (NSString *) applicationDocumentsDirectory;
#end
Implementation File:
#import "TST_ViewController.h"
#interface TST_ViewController ()
#end
#implementation TST_ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *dbFilename = #"db.sql";
NSString *userPath = [[TST_ViewController applicationDocumentsDirectory] stringByAppendingPathComponent:dbFilename];
NSString *srcPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbFilename];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL foundInBundle = [fileManager fileExistsAtPath:srcPath];
BOOL foundInUserPath = [fileManager fileExistsAtPath:userPath];
BOOL copySuccess = FALSE;
NSError *error;
if(foundInBundle) {
if (!foundInUserPath) {
NSLog(#"Don't have a writable copy, so need to create one...");
copySuccess = [fileManager copyItemAtPath:srcPath toPath:userPath error:&error];
}
if (!copySuccess) {
NSLog(#"Failed with message: '%#'.",[error localizedDescription]);
}
} else {
// handle error in the event the file is not included in the bundle
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
+ (NSString *) applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
#end

Small amount of unwanted data going to iCloud

I don't want anything to be backed up to iCloud. However, my data cannot be recreated, so I need to place it in my application's documents directory. For each file, I did the standard:
- (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
return [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:nil];
}
}
I have 5mB of data in there. But my app is still registering 0.2kB in iCloud (Through settings->iCLoud->Manage Storage). So, just to be sure, I did this:
-(void)resetBackupAttributes {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *fileListAct = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];
for (NSString *path in fileListAct) {
[self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:path]];
}
NSArray *paths2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths2 objectAtIndex:0];
NSArray *fileListCache = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:cacheDirectory error:nil];
for (NSString *path in fileListCache) {
[self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:path]];
}
NSArray *paths3 = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES);
NSString *preferencesDirectory = [paths3 objectAtIndex:0];
NSArray *fileListPref = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:preferencesDirectory error:nil];
for (NSString *path in fileListPref) {
[self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:path]];
}
}
It still has 0.2kB! Is there something I am missing? Does a small amount of data gets backed up regardless... like a directory tree or something? What I really want to know is, will this 0.2kB get me rejected for not following the data storage guidelines?
ok so I will put my comment into an answer:
is it possible that your apps default plist gets backed up in the
cloud? - BUT you could hook up a proxy between your iOS (simulator)
and the internet. Just catch all outgoing data and see whats actually
get transmitted ;). e.g. SquidMan
here's the link to SquidMan just in case …
As you said you think its the plist too. You can verify that by setting a key with some junk data and see if the total amount rises. ;)

How can I use iCloud to synchronize a .zip file between my apps?

Is it possible to upload a .zip file to iCloud, and then have it be synchronized across all of a user's iOS devices?
If so, how would I go about doing this?
If there is any File size limit, then also mention max. file size allowed.
This is how I synchronized zip files with iCloud .
Steps:
1) http://transoceanic.blogspot.in/2011/07/compressuncompress-files-on.html
. Refer this link to download zip api which is having code for zipping and unzipping folder.
2) Now all you need to play with NSData.
3) "MyDocument.h" file
#import <UIKit/UIKit.h>
#interface MyDocument : UIDocument
#property (strong) NSData *zipDataContent;
#end
4)
#import "MyDocument.h"
#implementation MyDocument
#synthesize zipDataContent;
// Called whenever the application reads data from the file system
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError
{
self.zipDataContent = [[NSData alloc] initWithBytes:[contents bytes] length:[contents length]];
[[NSNotificationCenter defaultCenter] postNotificationName:#"noteModified" object:self];
return YES;
}
// Called whenever the application (auto)saves the content of a note
- (id)contentsForType:(NSString *)typeName error:(NSError **)outError
{
return self.zipDataContent;
}
#end
5) Now somewhere in your app you need to zip folder and sync with icloud.
-(BOOL)zipFolder:(NSString *)toCompress zipFilePath:(NSString *)zipFilePath
{
BOOL isDir=NO;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pathToCompress = [documentsDirectory stringByAppendingPathComponent:toCompress];
NSArray *subpaths;
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:pathToCompress isDirectory:&isDir] && isDir){
subpaths = [fileManager subpathsAtPath:pathToCompress];
} else if ([fileManager fileExistsAtPath:pathToCompress]) {
subpaths = [NSArray arrayWithObject:pathToCompress];
}
zipFilePath = [documentsDirectory stringByAppendingPathComponent:zipFilePath];
//NSLog(#"%#",zipFilePath);
ZipArchive *za = [[ZipArchive alloc] init];
[za CreateZipFile2:zipFilePath];
if (isDir) {
for(NSString *path in subpaths){
NSString *fullPath = [pathToCompress stringByAppendingPathComponent:path];
if([fileManager fileExistsAtPath:fullPath isDirectory:&isDir] && !isDir){
[za addFileToZip:fullPath newname:path];
}
}
} else {
[za addFileToZip:pathToCompress newname:toCompress];
}
BOOL successCompressing = [za CloseZipFile2];
if(successCompressing)
return YES;
else
return NO;
}
-(IBAction) iCloudSyncing:(id)sender
{
//***** PARSE ZIP FILE : Pictures *****
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
if([self zipFolder:#"Pictures" zipFilePath:#"iCloudPictures"])
NSLog(#"Picture Folder is zipped");
ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];
ubiquitousPackage = [[ubiq URLByAppendingPathComponent:#"Documents"] URLByAppendingPathComponent:#"iCloudPictures.zip"];
mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
NSString *zipFilePath = [documentsDirectory stringByAppendingPathComponent:#"iCloudPictures"];
NSURL *u = [[NSURL alloc] initFileURLWithPath:zipFilePath];
NSData *data = [[NSData alloc] initWithContentsOfURL:u];
// NSLog(#"%# %#",zipFilePath,data);
mydoc.zipDataContent = data;
[mydoc saveToURL:[mydoc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
{
if (success)
{
NSLog(#"PictureZip: Synced with icloud");
}
else
NSLog(#"PictureZip: Syncing FAILED with icloud");
}];
}
6) You can unzip data received from iCloud like this.
- (void)loadData:(NSMetadataQuery *)queryData {
for (NSMetadataItem *item in [queryData results])
{
NSString *filename = [item valueForAttribute:NSMetadataItemDisplayNameKey];
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
MyDocument *doc = [[MyDocument alloc] initWithFileURL:url];
if([filename isEqualToString:#"iCloudPictures"])
{
[doc openWithCompletionHandler:^(BOOL success) {
if (success) {
NSLog(#"Pictures : Success to open from iCloud");
NSData *file = [NSData dataWithContentsOfURL:url];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *zipFolder = [documentsDirectory stringByAppendingPathComponent:#"Pics.zip"];
[[NSFileManager defaultManager] createFileAtPath:zipFolder contents:file attributes:nil];
//NSLog(#"zipFilePath : %#",zipFolder);
NSString *outputFolder = [documentsDirectory stringByAppendingPathComponent:#"Pictures"];//iCloudPics
ZipArchive* za = [[ZipArchive alloc] init];
if( [za UnzipOpenFile: zipFolder] ) {
if( [za UnzipFileTo:outputFolder overWrite:YES] != NO ) {
NSLog(#"Pics : unzip successfully");
}
[za UnzipCloseFile];
}
[za release];
NSError *err;
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:outputFolder error:&err];
if (files == nil) {
NSLog(#"EMPTY Folder: %#",outputFolder);
}
// Add all sbzs to a list
for (NSString *file in files) {
//if ([file.pathExtension compare:#".jpeg" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
NSLog(#" Pictures %#",file);
// NSFileManager *fm = [NSFileManager defaultManager];
// NSDictionary *attributes = [fm fileAttributesAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,file] traverseLink:NO];
//
// NSNumber* fileSize = [attributes objectForKey:NSFileSize];
// int e = [fileSize intValue]; //Size in bytes
// NSLog(#"%#__%d",file,e);
}
}
else
{
NSLog(#"Pictures : failed to open from iCloud");
[self hideProcessingView];
}
}];
}
}
}
In order to enabling Document storage in iCloud your "document" needs to be encapsulated in a UIDocument object.
Because UIDocument links to a file URL, you can easily create a UIDocument pointing to file://myzipfile.zip and then upload a zip document to iCloud.
I hope this helps
Probably this tutorial can help you more:
http://www.raywenderlich.com/6015/beginning-icloud-in-ios-5-tutorial-part-1

Objective-c: How to handle errors when loading a simple txt file

I'm trying to load a simply TXT file into a NSMutableArray. My file is called NoteBook.txt. For the following purposes (handling errors), I deleted NoteBook.txt so that the App could actually NOT load it.
In the following code, I try to find out if the file exist in my Docs Folder which I'd like to load. The following code should actually NOT attempt to load the file as there isn't one. However, it does so nonetheless and I am wondering what I am doing wrong?
Imagine that the string #"NoteBook.txt" is passed to the following method and that there is no such file in the Docs Folder of the App:
-(void) loadNoteBook:(NSString *)nameOfNoteBook
{
NSLog(#"Starting method 'LoadNoteBook...'");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory
//NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"NoteBook.txt"];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:nameOfNoteBook];
NSError *error;
if (filePath) { // check if file exists - if so load it:
NSLog(#"Loading notebook: %#", nameOfNoteBook);
NSString *tempTextOut = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:&error];
self.NoteBook = [[[tempTextOut componentsSeparatedByString: #"\n*----------*\n"] mutableCopy] autorelease];
}
else
{
// GENERATE mutable ARRAY
NSLog(#"Loading notebook failed, creating empty one...");
NoteBook = [[NSMutableArray alloc] init];
for (int temp = 0; temp < 6; temp++) {
[NoteBook insertObject:#"Empty" atIndex:temp];
}
}
}
Thanks for any suggestions, I'd really appreciate your help.
The problem is that you're checking if the NSString is set, not the path itself.
What you should probably do is check the path with NSFileManager fileExistsAtPath:isDirectory:
BOOL isDir;
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
if ([fileManager fileExistsAtPath:filePath isDirectory:&isDir] && !isDir) {
//file exists and is not a directory
}
You've got it already in your code:
NSString *tempTextOut = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:&error];
if(!tempTextOut) {
if(error) {
// error specific code to execute
NSLog(#"error loading file %#: %#", filePath, error);
}
// GENERATE mutable ARRAY
NSLog(#"Loading notebook failed, creating empty one...");
NoteBook = [[NSMutableArray alloc] init];
for (int temp = 0; temp < 6; temp++) {
[NoteBook insertObject:#"Empty" atIndex:temp];
}
} else {
self.NoteBook = [[[tempTextOut componentsSeparatedByString: #"\n*----------*\n"] mutableCopy] autorelease];
}
You test on filePath, which is actually just a string you've created. You don't test if there is a file behind it. Even if
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
does return an empty string you still append nameOfNoteBook to it and will if put in an if statement, testing against a non empty string will evaluate to true.