Which is the best way to store the downloaded images? From there I should be able to use them anywhere in my application, and images should not be deleted at any case (like low space). Any help please.
As per the standard, App related files(Data) need to be stored in document directory only. Once image get download store that images in document directory and maintain unique name for image identification.
-(NSString *)writeDataAsFile:(NSData *)imageData
{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDirectory = [paths objectAtIndex:0];
NSString * thumbNailFilename = [NSString stringWithFormat:#"%#.png",[self GetUUID]]; // Create unique iD
NSString * thumbNailAppFile = [documentsDirectory stringByAppendingPathComponent:thumbNailFilename];
if ([imageData writeToFile:thumbNailAppFile atomically:YES])
{
return thumbNailFilename;
}
return nil;
}
use this method to store the image(downloaded NSData) in document directory.
Retrieve image from the document directory like this
UIImage *thumbnailHomeImage = [UIImage imageWithContentsOfFile:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"%#",imageName]];
take a look at this image caching library. ive used it quite a few times, its really useful
Related
My scenario goes in this way. At the start of application a list of images will be downloaded from server & once downloaded all images will be converted into the static images and onwards will be using those static images everywhere in application. I think in android this thing can be achieved using BITMAP. (Not confirm).
Currently i'm using SDWEBIMAGE library for downloading and caching images. But i don't want to use this library anymore. I just want to download all images once and then everywhere i want to add below code snippet for displaying downloaded images.
[ImageView setImage:[UIImage imageNamed:#"DownloadedImageName"]];
Is there any way to get this thing done in ios?
You have to download each Image and save it into "Documents" Directory, and then whenever you need them use that.
For saving image into documents directory, use code like this:
- (IBAction)saveImage:(UIImage*)img {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
NSData *imageData = UIImagePNGRepresentation(img);
[imageData writeToFile:savedImagePath atomically:NO];
}
And for getting and show image on imageview, use this code:
- (UIImage*)getImage
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *getImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
UIImage *img = [UIImage imageWithContentsOfFile:getImagePath];
return img;
}
[UIImage imageNamed:] method is only for getting images that already exist in your app bundle. So if you have dynamic content that is downloaded from internet, you cannot use this method. Rather, create your own method to load the images from sandbox Documents folder.
I am writing an app which downloads image from my server and stores them locally for offline viewing. The codes I use to store the image locally are shown below. Apart from storing the image, I am also able to read the image from the path (which I stored separately).
However when I re-run my code from Xcode to the iPhone (without uninstalling the app from the phone), the stored image file would be missing. Is this expected? Would I face similar issue when my app has been released on App Store and when the user updates the app? Is there a way to keep the file persistent when I re-run them when I update some codes in Xcode?
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"file.jpeg",]];
if (![imageData writeToFile:imagePath atomically:YES])
{
// Handling when there is an error
NSLog(#"Failed to store file at path %#",imagePath);
stored.text = #"";
}
else
{ // Handling when write is successful
NSLog(#"Imaged stored path is %#",imagePath);
stored.text = imagePath;
}
[imageView setImage:image];
The code to read the image is shown below:
NSString *imagePathToRead = stored.text;
NSLog(#"Retrieve image from %#",imagePathToRead);
UIImage *image = [UIImage imageWithContentsOfFile:imagePathToRead];
[imageView setImage:image];
I am posting the answer here from rmaddy which solved the issue I was facing. I am posting here so that others can benefit if they are facing similar issue.
For the storing portion:
The stored.text should never store the full path:
stored.text = imagePath;
Instead I should store #"file.jpeg" only.
For the Read portion:
I should always regenerate the full path below when I wanted to read the path instead of the code below:
NSString *imagePathToRead = stored.text;
The corrected codes are:
NSString *imagePathToRead = stored.text;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:imagePathToRead]];
NSLog(#"Retrieve image from %#",imagePath);
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
This solved the issue and the image is able to be read even though the app is re-installed through Xcode.
This was working for me yesterday morning and now it doesn't. So, I suspect something else changed to cause it...but I can't find the change. I've spent hours reverting my code back almost a week and still it's not working (and I know it was working yesterday morning). So, I'm hoping that in posting this specific issue (a symptom?) some ideas will surface that I can evaluate. Thanks.
I download images as they're needed:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *targetFile = [NSString stringWithFormat:#"%#/%#.%#", documentDirectory, imageName, imageType];
// only download those where an image exists
if(![imageType isEqualToString:#""])
{
// only download the file if there is not already a local copy.
if([filemgr fileExistsAtPath:targetFile] == NO)
{
NSMutableData *imageData = [[NSMutableData alloc] initWithLength:0];
[imageData appendData:data];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *thumbNailFilename = [NSString stringWithFormat:#"%#.%#", imageName, imageType];
NSString *thumbNailAppFile = [documentsDirectory stringByAppendingPathComponent:thumbNailFilename];
}
}
Then display them:
NSString *imageFullName = [NSString stringWithFormat:#"%#%#", [greetingObject valueForKey:#"gid"], [greetingObject valueForKey:#"itp"]];
NSString *fullImagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageFullName];
UIImage *greetingImage = [UIImage imageWithContentsOfFile:fullImagePath];
self.greetingImage.image = greetingImage;
The variables "imageFullName" and "fullImagePath" are populated with the correct data and the image files are present on the simulator in the specified directory. Yet, "greetingImage" equals nil.
Here's what I get for "fullImagePath": /Users/Steve2/Library/Application Support/iPhone Simulator/7.1/Applications/8C9F8417-F6E2-4B38-92B3-82A88477CB7F/Documents/165.jpg
Here are the image files:
I have also tried variations using initWithContentsOfFile and dataWithContentsOfFile and get the same result. The greetingImage variable is nil.
I appreciate your ideas. I've even reinstalled Xcode in hopes that something got corrupted. No dice.
Added: One thing I just thought of... I did add the SystemConfiguration.framework to the project yesterday for an unrelated feature. It's currently at the top of the Linked Frameworks and Libraries list. I have no experience working with this. Could it be causing the problem?
Thanks.
Your code looks correct.
I would check that the images themselves are still okay. Looking at the screenshot you posted Finder isn't showing previews of the images which it should do with a valid JPEG. You say that the images are being downloaded so I suspect that they are being corrupted somehow on the way down.
EDIT:
Didn't notice that you were using initWithContentsOfFile. Since you are saving the files as NSData objects you will need to load them into memory as NSData objects and then init a UIImage with the data object, like so:
NSData *imageData = [NSData dataWithContentsOfFile:filePath];
[UIImage imageWithData:imageData];
What I've known:
How make requests to server for uploading I will use AFNetworking
How access photos and videos with help of ALAssetsLibrary
I think I must use CoreData to keep info about:last syncing, photos already uploaded, etc. I worked already with coreData it will no be a problem.
My problems are logic, flow how can achieve this auto back up and of course to be optimum(minimum requests, short way). What steps must follow to achieve this scope?
Any thoughts?
I think CoreData is too heavy in this situation. You may want to use plist to store your info data .here are some steps to follow .
After loading image from server, create a dictionary to store the message you want and create another dictionary to store these messages , and use image's url as the key of this dictionary. It might look like this:
imageUrl = {
lastSyncTime = xxxxxxxxxx,
photoUploaded = 0,
}
Create a plist file to save this dictionary:
- (NSString *)filePath:(NSString *) fileName{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:fileName];
}
[yourImageDictionary writeToFile:[self filePath:#"imageInfo.plist"] atomically:YES];
Read or write your plist file anytime you want:
if ([[NSFileManager defaultManager] fileExistsAtPath:[self filePath:#"imageInfo.plist"]]) {
NSDictionary *imageInfo = [NSDictionary dictionaryWithContentsOfFile:[self filePath:#"imageInfo.plist"]];
}
Usually it's the other way around, you use the path to display the image. I was wondering if you can get the path if you already have the image.
if you already have the image i.e. have added the file to your resources, you can use this to get the file path;
NSString *string = [[NSBundle mainBundle] pathForResource:#"IMAGE_FILE_NAME" ofType:#"jpg"]; // or ofType:#"png", etc.
I don't believe it is possible to get it directly from UIImage.
Best way is to save the image in a directory, then you will have the file path.
//image is your UIImage;
if (image != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"test.png" ];
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:path atomically:YES];
}
path will be your filepath.
Once a UIImage is created, the image data is loaded into memory and no longer connected to the file on disk. As such, the file can be deleted or modified without consequence to the UIImage and there is no way of getting the source path from a UIImage.