iPhone: Downloading Image then Displaying in UIImageView with #2x Extension - ios

I'm trying to download an image from the NSUrl imageURL and display it in a UIImageView with retina pixel density by adding the #2x; this is to be displayed on an iPhone 4 or later. I've used some code from here: How do I download and save a file locally on iOS using objective C?
It shows nothing on the imageView when I start it, and the last NSLog line prints out some really tiny dimensions for the image, suggesting that it didn't really download one. What is wrong with my code besides it having really bad error checking?
- (void) presentImage: (NSURL*) imageURL{
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
NSLog([imageURL description]);
if ( imageData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"0#2x.png"];
[imageData writeToFile:filePath atomically:YES];
}
else NSLog(#"Error when loading image!!!");
imageData = [NSData dataWithContentsOfFile:#"0#2x.png"];
UIImage *image = [[UIImage alloc] initWithData: imageData];
NSLog(#"%f1 x %f2", image.size.width, image.size.height);
[self.imageView setImage: image];
}
EDIT: OK, I fixed that. I feel stupid. I was supposed to put in
imageData = [NSData dataWithContentsOfFile:#filePath];
and put filePath in scope nstead of just putting in #"0#2x.png".

You're overcomplicating the issue I think. Use this method:
+ (UIImage *)imageWithData:(NSData *)data scale:(CGFloat)scale
And set the scale to 2.0 when you have a retina image.
-(void)presentImage:(NSURL*)imageURL {
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData scale:2.0];
[self.imageView setImage: image];
}

Related

How to add images in Array ios?

below image After editing the image when i click the share/save button how add images in array. i should be display in tableview and it have save locally.
You can convert a UIImage to NSData like this:
If PNG image
UIImage *image = [UIImage imageNamed:#"imageName.png"];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
If JPG image
UIImage *image = [UIImage imageNamed:#"imageName.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
Add imageData to array:
[self.arr addObject:imageData];
Load images from NSData:
UIImage *img = [UIImage imageWithData:[self.arr objectAtIndex:0]];
Do not store images into an array or a dictionary, unless you want to create a cache, but caches should evict their contents in a future.
You are working on a mobile device that even if is powerful it doesn't has the same hardware of your Mac.
Memory is a limited resource and should be managed with judgment.
If you want to cache temporary those images for performance reason, you can use NSCache, basically is works like mutable dictionary but it is thread safe.
If you want to save them locally it's fine but just keep the path to them in the the array.
- (NSString*) getDocumentsPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = paths[0]; //Get the document directory
return documentsPath;
}
- (NSString*) writePNGImage: (UIImage*) image withName: (NSString*) imageName {
NSString *filePath = [[self getDocumentsPath] stringByAppendingPathComponent:imageName]; // Add file name
NSData *pngData = UIImagePNGRepresentation(image);
BOOL saved = [pngData writeToFile:filePath atomically:YES]; //Write the file
if (saved) {
return filePath;
}
return nil;
}
- (UIImage*) readImageAtPath:(NSString*) path {
NSData *pngData = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:pngData];
return image;
}

Save images in iOS app which are loaded once when internet connection is available

I am creating a app in which i am saving some user detail and their messages, This app works similar to Facebook or many other i mean first time data come from api's and then i will store it in our local database. So the data which is loaded once is store in local database and user can see it without internet connection. I have store messages and detail in sqlite database it works fine with text messages and save detail of user.
The Problem is that i want to save profile image with user detail in local storage, i don't want to save it in database but save it into app directory for that i am using this below code
UIImageView *ProfileImage = [[UIImageView alloc]initWithFrame:CGRectMake(5, 1, 30, 30)];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSData *imageData =[NSData dataWithContentsOfURL:[NSURL URLWithString: [NSString stringWithFormat:#"http://ton.hiitap.com/p/%#",[TOUSERUDID objectAtIndex:i]]]];
NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:#"/%#.png",[TOUSERUDID objectAtIndex:i] ]];
[imageData writeToFile:imagePath atomically:YES];
UIImage* img = [UIImage imageWithData:imageData];
NSData *pngData = UIImagePNGRepresentation(img);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-%d.png",[TOUSERUDID objectAtIndex:i],i]]; //Add the file name
[pngData writeToFile:filePath atomically:YES];
pngData = [NSData dataWithContentsOfFile:filePath];
UIImage *img2 = [UIImage imageWithData:pngData];
dispatch_async(dispatch_get_main_queue(),^{
ProfileImage.image=img2;
});
});
The Problem with this code is it only save 2 users profile image and the images which are repeated are not shown when no internet connection is available. Can anyone suggest how to save all users profile images even they are repeated. So that they are shown when no internet connection is available. Thanks in advance.
if you are using core data you can create a column for example userImage with the type NSData in your user model
and you can convert you image to NSData like this :
if PNG image :
UIImage *image = [UIImage imageNamed:#"imageName.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
if JPG image :
UIImage *image = [UIImage imageNamed:#"imageName.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
and you can load the image from the database like this :
NSManagedObject *selectedObject = [[self yourFetchCOntroller] objectAtIndexPath:indexPath];
UIImage *image = [UIImage imageWithData:[selectedObject valueForKey:#"image"]];
// and set this image in to your image View
yourimageView.image=image;

Can't Reload UIImage from Saved file in iPhone Documents Directory location

I am making an app that will save a file to the iPhones Documents Directory and then when the View Controller is reloaded it will fetch it from that same location and display it. But it is not fetching it and displaying it.
I am using the following method to save the image:
void UIImageWriteToFile(UIImage *image, NSString *fileName)
{
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectoryPath = dirPaths[0];
NSString *filePath = [documentDirectoryPath stringByAppendingPathComponent:fileName];
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
}
I am trying to recall the image I have saved from the viewDidLoad method with the following code:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectoryPath = dirPaths[0];
NSString *fileName = [NSString stringWithFormat:#"/%#.png", self.fullname.text];
NSString *filePath = [documentDirectoryPath stringByAppendingString:fileName];
[self.imageView setImage:[UIImage imageNamed: filePath]];
However, it is not showing my image. Can anyone help me and tell me where I am going wrong please. I am new to iOS Development.
replace this line: [self.imageView setImage:[UIImage imageNamed: filePath]];
with this one :
UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
[self.imageView setImage:image];
You can use [UIImage imageNamed:] with images from the Documents folder and have the benefits of the underlying caching mechanism, but the file path is slightly different.
Use the following:
NSString *fileName = [NSString stringWithFormat:#"../Documents/%#.png", self.fullname.text];
UIImage *image = [UIImage imageNamed:fileName];
You need to use method
- (UIImage*)initWithContentsOfFile:(NSString*)path
to init images from Documents or Cache directories.
imageNamed: is used for getting images from application bundle.

Can I async UIImageJPEGRepresentation writeToFile?

I am doing the following when I get an image back from the server. But this code is bringing my app to its knees. It freezes up the UI.
Can this be run on a background thread in iOS? Can I use async?
if (![NSString isEmpty:user.avatarURL])
{
NSString *pathToImage = user.avatarURL;
NSURL *url = [NSURL URLWithString:pathToImage];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [[UIImage alloc] initWithData:data];
[[NSUserDefaults standardUserDefaults] setObject:UIImageJPEGRepresentation(image, 1) forKey:kUserImage];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:#"userAvatar.png" ];
NSData* jpegdata = UIImageJPEGRepresentation(image, 1);
[jpegdata writeToFile:path atomically:YES];
}
As #valentin says, you can do everything inside the if() statement in a dispatch_async() call.
Note I suspect what’s probably slowing you down is actually the -dataWithContentsOfURL:, not the UIImageJPEGRepresentation(), so you’ll want to make sure that’s inside your dispatch_async, not outside.
Also, I’m not clear why you’re decompressing the data into an image, then re-compressing it. You’re going to get artifacts doing this, and with most services the avatar image is going to be compressed anyhow.
I’d do the following:
if (user.avatarURL)
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *const imageURL = [NSURL URLWithString:user.avatarURL];
if (!imageURL)
return;
NSData *const imageDdata = [NSData dataWithContentsOfURL:imageURL];
if (!imageDdata.length)
return;
[[NSUserDefaults standardUserDefaults] setObject:imageDdata forKey:kUserImage];
[imageDdata writeToFile:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:#"userAvatar.png"] atomically:YES];
});
The line which is doing most damage is:
NSData *data = [NSData dataWithContentsOfURL:url];
Because it does the download from the network. Nothing in your code updates the UI so it can all be run on a background thread. Just ensure that if you post a notification or subsequently update the UI after the image is saved that you switch back to the main thread.

UIImagePickerController delegate method not re-saving/overwriting new pictures taken

I'm using a simple implementation of UIImagePickerController to take a picture and save it to my app directory. I"m running into problems with didFinishPickingMediaWithInfo, where I retrieve the image from the info, convert it into NSData using UIImageJPEGRepresentation, and then save it to a file. Problem is, the NSData object appears never to be overwritten, so the first time I take a picture it saves the picture just fine, but any subsequent pictures are not saved, because when I redisplay the image located at the filePath I'm saving it to, it's always the very first picture I took.
I have NSLog statements right now printing out the hash of the UIImage and of the NSData object I'm saving the image to. The UIImage hash changes each time, but the NSData hash is exactly the same all the time...shouldn't that change too?
My code is below. Note that everything not declared in the delegate method below is a global var that isn't causing me any trouble (at least they don't seem to be).
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory, fileNameString];
NSData *imageData = UIImageJPEGRepresentation(image, 0.5f);
// imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 0.5f)];
[imageData writeToFile:filePath atomically:YES];
[self dismissModalViewControllerAnimated:YES];
}
When I get rid of the NSData object entirely and replace all instances of
imageData
with
UIImageJPEGRepresentation(image, 0.5f)
I still have the same problem, namely that the hash of UIImageJPEGRepresentation(image, 0.5f) is always the same, even though the hash of the UIImage it takes as a parameter always changes.
Try this:
NSData *imageData = UIImageJPEGRepresentation(image, 0.5f);
imageData = [NSKeyedArchiver archivedDataWithRootObject:imageData];
//imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 0.5f)];
NSError *error= nil;
[imageData writeToFile:filePath options:NSDataWritingAtomic error:&error];
Also take a look at this link
Are you creating the directory? Use this code to create the directory:
NSArray* dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* docsDir = [dirPaths objectAtIndex:0];
pathString = [docsDir stringByAppendingPathComponent:#"%#",filePath];
NSFileManager* filemgr = [NSFileManager defaultManager];
//Creates Directory
if ([filemgr createDirectoryAtPath:pathString
withIntermediateDirectories:YES
attributes:nil
error: NULL] == YES){

Resources