Can I load a UIImage from a URL? - ios

I have a URL for an image (got it from UIImagePickerController) but I no longer have the image in memory (the URL was saved from a previous run of the app). Can I reload the UIImage from the URL again?
I see that UIImage has a imageWithContentsOfFile: but I have a URL. Can I use NSData's dataWithContentsOfURL: to read the URL?
EDIT1
based on #Daniel's answer I tried the following code but it doesn't work...
NSLog(#"%s %#", __PRETTY_FUNCTION__, photoURL);
if (photoURL) {
NSURL* aURL = [NSURL URLWithString:photoURL];
NSData* data = [[NSData alloc] initWithContentsOfURL:aURL];
self.photoImage = [UIImage imageWithData:data];
[data release];
}
When I ran it the console shows:
-[PhotoBox willMoveToWindow:] file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG
*** -[NSURL length]: unrecognized selector sent to instance 0x536fbe0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL length]: unrecognized selector sent to instance 0x536fbe0'
Looking at the call stack, I'm calling URLWithString, which calls URLWithString:relativeToURL:, then initWithString:relativeToURL:, then _CFStringIsLegalURLString, then CFStringGetLength, then forwarding_prep_0, then forwarding, then -[NSObject doesNotRecognizeSelector].
Any ideas why my NSString (photoURL's address is 0x536fbe0) doesn't respond to length? Why does it say it doesn't respond to -[NSURL length]? Doesn't it know that param is an NSString, not a NSURL?
EDIT2
OK, the only problem with the code is the string to URL conversion. If I hardcode the string, everything else works fine. So something is wrong with my NSString and if I can't figure it out, I guess that should go in as a different question. With this line inserted (I pasted the path from the console log above), it works fine:
photoURL = #"file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG";

You can do it this way (synchronously, but compact):
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:MyURL]]];
A much better approach is to use Apple's LazyTableImages to preserve interactivity.

You can try SDWebImage, it provides:
Asynchronous loading
Caching for offline use
Place holder image to appear while loading
Works well with UITableView
Quick example:
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];

And the swift version :
let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
var err: NSError?
var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
var bgImage = UIImage(data:imageData)

If you're really, absolutely positively sure that the NSURL is a file url, i.e. [url isFileURL] is guaranteed to return true in your case, then you can simply use:
[UIImage imageWithContentsOfFile:url.path]

get DLImageLoader and try folowing code
[DLImageLoader loadImageFromURL:imageURL
completed:^(NSError *error, NSData *imgData) {
imageView.image = [UIImage imageWithData:imgData];
[imageView setContentMode:UIViewContentModeCenter];
}];
Another typical real-world example of using DLImageLoader, which may help someone...
PFObject *aFacebookUser = [self.fbFriends objectAtIndex:thisRow];
NSString *facebookImageURL = [NSString stringWithFormat:
#"http://graph.facebook.com/%#/picture?type=large",
[aFacebookUser objectForKey:#"id"] ];
__weak UIImageView *loadMe = self.userSmallAvatarImage;
// ~~note~~ you my, but usually DO NOT, want a weak ref
[DLImageLoader loadImageFromURL:facebookImageURL
completed:^(NSError *error, NSData *imgData)
{
if ( loadMe == nil ) return;
if (error == nil)
{
UIImage *image = [UIImage imageWithData:imgData];
image = [image ourImageScaler];
loadMe.image = image;
}
else
{
// an error when loading the image from the net
}
}];
As I mention above another great library to consider these days is Haneke (unfortunately it's not as lightweight).

Try this code, you can set loading image with it, so the users knows that your app is loading an image from url:
UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"loading.png"]];
[yourImageView setContentMode:UIViewContentModeScaleAspectFit];
//Request image data from the URL:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://yourdomain.com/yourimg.png"]];
dispatch_async(dispatch_get_main_queue(), ^{
if (imgData)
{
//Load the data into an UIImage:
UIImage *image = [UIImage imageWithData:imgData];
//Check if your image loaded successfully:
if (image)
{
yourImageView.image = image;
}
else
{
//Failed to load the data into an UIImage:
yourImageView.image = [UIImage imageNamed:#"no-data-image.png"];
}
}
else
{
//Failed to get the image data:
yourImageView.image = [UIImage imageNamed:#"no-data-image.png"];
}
});
});

Check out the AsyncImageView provided over here. Some good example code, and might even be usable right "out of the box" for you.

AFNetworking provides async image loading into a UIImageView with placeholder support. It also supports async networking for working with APIs in general.

Make sure enable this settings from iOS 9:
App Transport Security Settings in Info.plist to ensure loading image from URL so that it will allow download image and set it.
And write this code:
NSURL *url = [[NSURL alloc]initWithString:#"http://feelgrafix.com/data/images/images-1.jpg"];
NSData *data =[NSData dataWithContentsOfURL:url];
quickViewImage.image = [UIImage imageWithData:data];

The way using a Swift Extension to UIImageView (source code here):
Creating Computed Property for Associated UIActivityIndicatorView
import Foundation
import UIKit
import ObjectiveC
private var activityIndicatorAssociationKey: UInt8 = 0
extension UIImageView {
//Associated Object as Computed Property
var activityIndicator: UIActivityIndicatorView! {
get {
return objc_getAssociatedObject(self, &activityIndicatorAssociationKey) as? UIActivityIndicatorView
}
set(newValue) {
objc_setAssociatedObject(self, &activityIndicatorAssociationKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
}
}
private func ensureActivityIndicatorIsAnimating() {
if (self.activityIndicator == nil) {
self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
self.activityIndicator.hidesWhenStopped = true
let size = self.frame.size;
self.activityIndicator.center = CGPoint(x: size.width/2, y: size.height/2);
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.addSubview(self.activityIndicator)
self.activityIndicator.startAnimating()
})
}
}
Custom Initializer and Setter
convenience init(URL: NSURL, errorImage: UIImage? = nil) {
self.init()
self.setImageFromURL(URL)
}
func setImageFromURL(URL: NSURL, errorImage: UIImage? = nil) {
self.ensureActivityIndicatorIsAnimating()
let downloadTask = NSURLSession.sharedSession().dataTaskWithURL(URL) {(data, response, error) in
if (error == nil) {
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.activityIndicator.stopAnimating()
self.image = UIImage(data: data)
})
}
else {
self.image = errorImage
}
}
downloadTask.resume()
}
}

The Best and easy way to load Image via Url is by this Code:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data =[NSData dataWithContentsOfURL:[NSURL URLWithString:imgUrl]];
dispatch_async(dispatch_get_main_queue(), ^{
imgView.image= [UIImage imageWithData:data];
});
});
Replace imgUrl by your ImageURL
Replace imgView by your UIImageView.
It will load the Image in another Thread, so It will not slow down your App load.

Local URL's are super simple, just use this :
UIImage(contentsOfFile: url.path)

Related

How to load images into uicollectionview cell from url asynchronous

I have a method that I'm calling from cell in the viewForRowAtIndexPath method.
The method containts only this code
NSURL *imageURL = [NSURL URLWithString:urlString];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^(void){
completionBLock(image);
});
Images are loading very slowly and sometimes not at all. Everytime the cell goes back into view the method gets called again.
This is in my cellForIndexPathRow
[Method getImage:brochureModel.brochureCoverUrl Oncompletion:^(UIImage *image) {
cell.imageView.image = image;
}];
How can I download images from a url and display it in a collection view reusable cells.
Note: I'm trying to not use any third party libraries for my app
My problem is with the caching of the images. I tried this with self.imageCache being a mutableDictionary.
if (self.imageCache[urlString]) {
UIImage *imageFromCache = self.imageCache[urlString];
onImageDidLoad(imageFromCache);
} else {
[API fetchImageFromUrl:urlString onDidLoad:^(UIImage *image) {
self.imageCache[urlString] = image;
onImageDidLoad(image);
}];
}

How to load url link to imageview properly and how to manage the image in cache?

NSString *img=[arrImages objectAtIndex:i];
imgScrollView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]];
I have displayed my code. The URL links have been stored into an array and the images are also fetching into uiimage view, but only the first two images are loaded into the imageview while the others didn't load .
arrImages:
inside image viewhttp://localhost:8888/welcome/company/0/images/TV Repair.png
this is the link present in the arrImages i don't know why first two images has been loading.
FOR LOOP:
for(NSDictionary *DicHoleCategories in ArrCategory)
{
StrName=[DicHoleCategories objectForKey:#"image"];
if(StrName!=nil)
{
subimages=[NSString stringWithFormat:LocalImage"%#",StrName];
[DicAllValues setObject:subimages forKey:#"image"];
NSError *error =nil;
}
[arrImages addObject:[DicAllValues objectForKey:#"image"]];
}
Can anyone find the issue and help me please?
Go through the below coding
//url string
NSString *ImageURL = #"yoururl";
//string to data conversion
NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
//set image
imageView.image = [UIImage imageWithData:imageData];
please follow the below code
if(StrName!=nil)
{
subimages=[NSString stringWithFormat:LocalImage"%#",StrName];
[DicAllValues setObject:subimages forKey:#"image"];
NSError *error =nil;
[arrImages addObject:[DicAllValues objectForKey:#"image"]];//add here!
}
Plz check now and tell me if its working or not!

How to find if image exists or not - parse

I have successfully retrieved the image (lets say user profile pic) from parse, and i'm displaying it in the ios app. But if there is no image in the file column, then i want to display default image which is stored in the locally (not in parse), not successful.
My simple question is, how to check if there is image or not ? Below is the simple code;
PFFile *userImage = [object objectForKey:#"profilePic"]; __block UIImage *userProfilePic =[[UIImage alloc]init];
[userImage getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
//this block will execute only if there is image
if(data) {
userProfilePic = [UIImage imageWithData:data];
userPic.image=userProfilePic;
}
//this block is not at all executing. This block should execute when user doesn't have their profile uploaded
if(!data) {
UIImage *userProfileDefaultPic = [[UIImage alloc]init];
userProfileDefaultPic=[UIImage imageNamed:#"defaultprofile.png"];
userPic.image=userProfileDefaultPic;
}
}
}];
Hope you can help me. Thanks in advance.
Pradeep
At last found the solution !
(!data) will not execute , instead we need to check if the PFFile and the UIImage to store PFFile has image or not, like below;
PFFile *userImage = [object objectForKey:#"profilePic"];
__block UIImage *userProfilePic =[[UIImage alloc]init];
if(userImage && ![userProfilePic isEqual:[NSNull null]]) //This is important to check if the file if image is there or not and if not, then display default pic in else part
{
[userImage getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if(!error)
{
userProfilePic = [UIImage imageWithData:data];
userPic.image=userProfilePic;
}
}];
}
else
{
userProfilePic =[UIImage imageNamed:#"defaultprofilepic.png"];
userPic.image=userProfilePic;
}
Your code already does that. You just need to set your image on the main thread and not background thread.
if(!data) { [dispatch_async(dispatch_get_main_queue(), ^{
UIImage *userProfileDefaultPic = [[UIImage alloc]init];
userProfileDefaultPic=[UIImage imageNamed:#"defaultprofile.png"];
userPic.image=userProfileDefaultPic;
}}];

app slowing down due to image load issue

I am having problem with the loading of content in the app, I see that the data is fetched by the app but the images take lot of time to load, is there any possibility to load images afterwords. The code is below:
NSDictionary *dict=[discussionArray objectAtIndex:indexPath.row];
UIImageView *avatarimage = (UIImageView *)[cell viewWithTag:4];
NSString *photoStrn=[dict objectForKey:#"photo"];
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSString *u=[NSString stringWithFormat:#"http://%#",photoStrn];
NSURL *imageURL=[NSURL URLWithString:u];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
dispatch_sync(dispatch_get_main_queue(), ^{
UIImage *dpImage = [UIImage imageWithData:imageData];
if (dpImage==nil)
{
dpImage = [UIImage imageNamed:#"profileImage.png"];
}
avatarimage.image = dpImage;
});
If you want more details I will provide :)
You can use GCD for doing this:
dispatch_async(dispatch_get_global_queue(0,0), ^{
for (NSDictionary *dic in discussionArray)
{
NSString *photoStr=[dic objectForKey:#"photo"];
NSString * photoString=[NSString stringWithFormat:#"http://%#",photoStr];
UIImage *dpImage = [UIImage imageWithData: [NSData dataWithContentsOfURL:[NSURL URLWithString:photoString]]];
if (dpImage==nil)
{
dpImage = [UIImage imageNamed:#"profileImage.png"];
}
}
});
Get SDWebImage Here and add that in your project and include
UIImageView+WebCache.h
in class implementation file
UIImageView *imag=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 40, 40)];
[imag setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[[jsonarray objectAtIndex:indexPath.row]valueForKey:#"imgurl"]]] placeholderImage:[UIImage imageNamed:#"Icon#2x.png"]];
[self.view addSubview:imag];
[imag release];
SDWebImage will be more useful for loading images from URL.
Hope this Helps !!!
James,
With this line,
[NSData dataWithContentsOfURL:[NSURL URLWithString:photoString]]]
you make a synchronous network call on the main thread. The current thread will hang untile the network call is complete.
The solution would be to do an asynchronous network call. The AFNetworking library provides a great category to load images asynchronously : UIImageView+AFNetworking.

How to convert data to image in iOS

NSData *imageData = UIImagePNGRepresentation(your_image_here);
After that i transferred it to another iPhone using bluetooth.
Now i need to convert the data back to image. Can any one tell me how to do it?
I assume this is to et back the data which you encoded in the previous question.
For converting UIImage to NSData ,
NSData* pictureData = UIImagePNGRepresentation(image);
To get it back,
UIImage *image = [[UIImage alloc]initWithData:pictureData];
Remember to add [image release] at the end.
or you can use
UIImage *image = [[UIImage alloc]init];
[image imageWithData:pictureData];
In swift-3 : Data is converted back to image by :--
func compressImage() -> UIImage {
let imageData = UIImageJPEGRepresentation(UIImage(named:"background.jpg")!, 0.2)
let image = UIImage(data: imageData!)
return image!
}
Just call imageWithData: or on instantiation, you can call initWithData:
[UIImage imageWithData:(NSData *)data];

Resources