Save image path to sqlite3 database - ios

I am having some troubles saving images path into Documents folder and store the path into my sqlite3 local db.
Today I successfully stored the images as BLOB into the db, but reading around the Internet, people said that this is not recommended.
So, now I'm trying to store image path in DB but..
Situation
User taps a button to choose an image (via UIImagePickerView) or take a new photo
After choosing the image, an imageView is set with the image chosen.
Code for picker:
-(void)imagePickerController:(UIImagePickerController *)pickr didFinishPickingMediaWithInfo:(NSDictionary *)info{
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
/* Test code for saving data */
//NSString *dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//NSString *pngPath = [NSString stringWithFormat:#"%#/test.png",dir];
//NSData *data = [NSData dataWithData:UIImagePNGRepresentation(image)];
//[data writeToFile:pngPath atomically:YES];
[imageView setImage:image];
picture = YES;
[pickr dismissModalViewControllerAnimated:YES];
}
Now I got a couple of questions
Into my db, image is BLOB type. Should I edit it to TEXT?
How is the path saved? I mean, in the test code /test.png is a generic image name. Does the chosen image name get saved too so that I can retrieve it? Or, better, if I save an image picked from my library with name "IMG0001", does it get saved as "test"?
What's the right way to save an image into documents folder, its path to the DB and then retrieve it?
I googled a lot to find an answer, but after experimenting a lot I gave up.
Thanks in advance

Here is nice tutorial on how to save images in Documents directory
You need to convert your BLOB field to TEXT field and just save file name of that image. You can also create folder in Documents directory and then access by foldername/filename.png.
Hope this information helps you..
EDIT
Here is code to check if that folder exits, If not exist create new that folder
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentsDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"MyFolder"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]){
NSError* error;
if( [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error])
;// success
else
{
NSLog(#"[%#] ERROR: attempting to write create MyFolder directory", [self class]);
NSAssert( FALSE, #"Failed to create directory maybe out of disk space?");
}
}

You cannot directly access the image from the user's photo library, since you have access only to your Applications Sandbox folder.
So if you don't want to store the image as a blob file in the database, you should save the image in the caches folder inside your App's documents folder and then store the filename you set to the image in the database.
Since all images are going to be in the same path folder, you don't need to actually save the entire path in the database, but only the filename should be sufficient enough.

Related

Is document directory path constant for iOS device?

I am saving video/image in document directory.Now once the image is saved in document directory I want to save its reference in my local database.So I am thinking I can save URL of the image in the local database.
So is it constant throughout my app?
It's not constant, i have observed every time you launch the app it'll be different, but your data is moved to this new path. You can save your file name in your database, and dynamically append this file name to NSDocument directory.
- (NSString *)documentsFilePath:(NSString *)fileName {
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths firstObject];
NSString *filePath = [docsDir stringByAppendingPathComponent:fileName];
return filePath;
}
- (void)storeFile:(NSString *)fileName {
NSString *filePath = [self documentsFilePath:fileName];
// create if needed
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
// Write your data to file system here...
}
}
- (void)deleteFile:(NSString *)fileName {
NSString *filePath = [self documentsFilePath:fileName];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSError *deleteErr = nil;
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&deleteErr];
if (deleteErr) {
NSLog(#"Can't delete %#: %#", filePath, deleteErr);
}
}
}
Please handle nil checks and store only filename in DB
No, it's not constant. Whenever your app reinstall or updated on device the document directory will change, because when app installed on device os made an directory for app with some random id and each install this random it get changed by OS.
So, you need to make it dynamic own your own, like store the file name only and append the document directory path while using it.
I would suggest only saving the filename or subdirectory/filename (if you have a subdirectory) in the database and then only attaching that to the NSDocumentDirectory.
This will ensure that you always know where the file is...
NSDocumentDirectory is however consistent accross updates, so the files should remain in the document directory even if you update...

QLPreviewController not displays saved file

I'm getting this behaviour using Xcode 8.0. The problem is, after downloading a file and storing it on documents directory (code provided below), QLPreviewController only displays document's name and size. The property currentPreviewItem returns the correct path document. What's even more strange, is that if I try to open that document from another controller in my app, it works fine. I've implemented both QLPreviewControllerDelegate and QLPreviewControllerDataSource.
Code for downloading and saving document:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSURL *url = [NSURL URLWithString:file[#"url"]];
NSData *data = [NSData dataWithContentsOfURL:url];
if (!data) {
completion([NSError new]);
return;
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:AppName];
path = [path stringByAppendingPathComponent:file[#"name"]];
file[#"filePath"] = [NSURL fileURLWithPath:path];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
completion(nil);
});
});
Then, when user selects a document I use the content saved on #"filePath" to show QLPreviewController. I've tried pushing it and presenting it modally and in both cases it just displays a gray page with document's name and size.
File wasn't showed because downloaded contents didn't contain file's extension. When I tried opening it in other controller, it worked because I temporary used another file name containing the correct extension. So I solved the problem adding the extension .pdf to downloaded files that didn't include it. This made QLViewController displaying correctly the file.
In my case, a file was created with the correct name, but the file contained an error message from the server, thus not representing the expected file structure.

How to save images inside app

Hi I'm new to iOS objective c.
I'm working on a app which fetches images and stores it in the app memory for reference.
when u click on the favourite it should go the favourites tab
when clicked on downloads.The image should go on the download tab.
as ALAasset is deprecated can some one explain what is the best way to store images.
is it using file or PHImagemanager.
and how?
You should store images in documents directory something like,
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
NSString *documentsDirectoryForSaveImages = [docsDir stringByAppendingPathComponent:#"/ProfileImages"];
[[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectoryForSaveImages withIntermediateDirectories:YES attributes:nil error:nil]; // This creates folder in document directory of name "ProfileImages"
Now you can store image something like,
NSData *data = UIImageJPEGRepresentation(responseObject, 1.0); //Convert image to data
[data writeToFile:[documentsDirectoryForSaveImages stringByAppendingPathComponent:formImage] atomically:NO]; //write that data to path. formImage is string value (name of image. Ideally should use timestamp to make unique naming)
You can retrieve image something like,
UIImage *img = [UIImage imageWithContentsOfFile:[documentsDirectoryForSaveImages stringByAppendingPathComponent:formImage]];
Hope this will help :)

Get Image Path from Images Directory in Supporting Files

I have a bunch of images stored in an images directory within my Supported Files directory in Xcode. I want to be able to show one of those images. What is the best way to obtain a path to that image? Do I have to copy them to the Documents directory first? If so, how can I do that?
EDIT: I've tried the following to copy the image from Supporting Files to the Documents folder in the app. It successfully copies, but I can't get the image to show:
-(void)findImage:(NSString *)imageName
{
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appImagePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.jpg",imageName]];
success = [fileManager fileExistsAtPath:appImagePath];
if (success)
{
return;
}
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultImagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.jpg",imageName]];
success = [fileManager copyItemAtPath:defaultImagePath toPath:appImagePath error:&error];
if (!success)
{
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
self.imageDisplay.image = [UIImage imageNamed:appImagePath];
return;
}
This should do the trick:
[UIImage imageNamed:#"someImageName"];
EDIT:
Some additional information:
-imageNamed: will look through the entire main bundle of the application for an imagefile (preferrably an png) with the filename of "someImageName". You need not worry about its location or its extension, since it will be searched for in the mainbundle. Files that you import through the import-file-dialogue in xcode will be added to he main bundle.
This means:
If i have imported a file called myImage.png, calling [UIImage imageNamed:#"myImage"];from anywhere in my code will get me a UIImage-Object containing that image. Its amazingly simple, and maybe that startled you a bit ;)
Look it up in the docs if you like:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIImage_Class/Reference/Reference.html

Proper way of saving and loading pictures

I am making a small app where the user can create a game profile, input some data and a picture that can be taken with the camera.
I save most of that profile data with the help of NSUserDefaults, but a friend discouraged me from saving the profile image in NSUserDefault.
What's the proper way to save and retrieve images locally in my app?
You should save it in Documents or Cache folder. Here is how to do it.
Saving into Documents folder:
NSString* path = [NSHomeDirectory() stringByAppendingString:#"/Documents/myImage.png"];
BOOL ok = [[NSFileManager defaultManager] createFileAtPath:path
contents:nil attributes:nil];
if (!ok)
{
NSLog(#"Error creating file %#", path);
}
else
{
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
[myFileHandle writeData:UIImagePNGRepresentation(yourImage)];
[myFileHandle closeFile];
}
Loading from Documents folder:
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
UIImage* loadedImage = [UIImage imageWithData:[myFileHandle readDataToEndOfFile]];
You can also use UIImageJPEGRepresentation to save your UIImage as a JPEG file. What's more if you want to save it in Cache directory, use:
[NSHomeDirectory() stringByAppendingString:#"/Library/Caches/"]
One way to do this is use the application's document directory. This is specific to a application and will not be visible to other applications.
How to create this:
Just add a static function to App Delegate and use the function where ever the path is required.
- (NSString )applicationDocumentDirectory {
/
Returns the path to the application's documents directory.
*/
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
Hope it Helped..
I think this("iphone-user-defaults-and-uiimages") post addresses your issue. Don't save blobs to a property list such as NSUserDefaults. In your case I would write to disk directly instead.

Resources