My UIImage is not loading the URL I specified with [NSData datawithContentsOfURL:], even though the URL is (seemingly) correct.
Here's my configureCell: method:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSString *url = [photoUrls objectAtIndex:indexPath.section];
cell.imageView.image = [UIImage imagewithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]];
}
Here's what is inside of the "photoUrls" array (excluding bullet points):
(
http://fbcdn.net/fakeurl1/839.jpg
http://fbcdn.net/fakeurl2/840.jpg
http://fbcdn.net/fakeurl3/841.jpg
)
I wouldn't use [nsdata dataWithContentsOfURL:] in configure cell as it will block the UI. And also the way you have it, it will redownload all the images over and over again.
The following links will help you download the data asynchronously with out blocking the UI.
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
https://github.com/rs/SDWebImage
With This SDWebImage all you have to do is:
[cell.imageView setImageWithURL:[NSURL URLWithString:urlString]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
it will take care of downloading the image.
Your URLs don't point to valid images. All I see is "Not found. Back to facebook". Your call to [NSData dataWithContentsOfURL:] will get the data, but [UIImage imageWithData:] will fail to generate a UIImage because the data doesn't represent a valid image.
Related
This question already has answers here:
Getting Image from URL Objective C
(5 answers)
Closed 4 years ago.
I am trying to fetch images from URL and displaying it on collection view how to do it ?
I have used following code but didnt get answer
(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
collectionGalleryTechrCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:Url];
//UIImage *image = [UIImage imageWithData:imageData];
//CollectionViewImage.image = image;
NSURL *urlBack = [NSURL URLWithString:#"http://ssk.com/zpschool1/web/gallery/download%20(4).jpg"];
NSData *urlDataBack = [NSData dataWithContentsOfURL:urlBack];
UIImage *imageBack = [UIImage imageWithData:urlDataBack];
cell.myImg.image =imageBack;
//cell.myImg.image = [UIImage imageWithData:ImgURL];
cell.myImg.userInteractionEnabled=YES;
return cell;
}
Loading and displaying image asynchronously is better then getting NSData from URL and displaying imageWithData in UICollectionView or UITableView.
You can check out this answer given in the link below :
https://stackoverflow.com/a/34041518/9332509
NSString *strImg_Path = [[NSString alloc]init];
strImg_Path = [NSString stringWithFormat:#"%#",[NSURL URLWithString:#"http://ssk.com/zpschool1/web/gallery/download%20(4).jpg"];
];
[cell.myImg sd_setImageWithURL:[NSURL URLWithString:strImg_Path]
placeholderImage:[UIImage imageNamed:#"placeholer_image"]];
make sure placeholer_image for default image and use framework - SDWebImage for lazy loading.
Use Url from your array for dynamic instead of static Url.
I have a mutable array of dictionary store image from url.So how to store image in application cache and i can view image when not have internet connection.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString * CellIndentifier=#"CustomCell";
CustomCell *cell = (CustomCell*)[collectionView dequeueReusableCellWithReuseIdentifier:CellIndentifier forIndexPath:indexPath];
NSDictionary *dictVideo = [self.videoList objectAtIndex:indexPath.row];
[cell.indicator startAnimating];
//set title
NSString *titleVideo = [dictVideo objectForKey:#"Title"];
[cell.myLabel setText:titleVideo];
// set image url
NSString *urlVideo = [dictVideo objectForKey:#"Url"];
NSURL *url = [NSURL URLWithString:urlVideo];
cell.imageView.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage * img = [[UIImage alloc]initWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(#"%ld %# %#",(long)indexPath.row,titleVideo,url);
[cell.imageView setImage: img];
[cell.indicator stopAnimating];
});
});
return cell;
}
you can use SDWebImage library as Umar Farooq said,Its support for both iOS 6 and 7
you can then use below code in your .m file
#import "UIImageView+WebCache.h"
UIImage *Noimg = [UIImage imageNamed:#"noimg.png"];
[cell.PlaceImg setImageWithURL:[NSURL URLWithString:strImgname] placeholderImage:Noimg];
Here Noimg is the placeholder image, its automatically manage by library when there is no image found on image location
NSURLCache already does this for you. Your application already has an implicit NSURLCache that may not have on disk persistence, so you want to explicitly set it:
NSURLCache *cache = [[NSURLCache alloc]initWithMemoryCapacity:(5 * 1024 * 1024) diskCapacity:(10 * 1024 *1024) diskPath:#"NSURLCache.db"];
[NSURLCache setSharedURLCache:cache];
And from that point on, the URL loading system will store data both in memory and on disk. This will allow it to be available when there is no connection. You continue to make requests as usual, they just return a lot faster when served out of the cache.
If you want to modify this behavior, you should modify the cache policy used by your NSURLRequest (for example, NSURLRequestReturnCacheDataElseLoad or NSURLRequestReturnCacheDataDontLoad). Unfortunately, you are using dataWithContentsOfURL: which does not provide an opportunity to do that. Using NSURLSessionTask or NSURLConnection would allow you to do so.
Keep in mind that the server does tell the client how long a response is valid for, and the default cache policy does obey that.
NSData *imageUrl = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.content objectAtIndex:indexPath.row] valueForKey:#"imageUrl"] ]];
cell.thumbnailImageView.image=[UIImage imageWithData:imageUrl];
this is how i use imageUrl to load them into UIImage but it takes a while to load and the program seems like it crashed or entered to an infinite loop.
How can i make the content of UIImage with url but faster?
I would suggest you to use AsyncImageView a beautiful implementation by Nicklockwood -father of iCarousel.
Link
it is very simple to use.
#import "AsyncImageView.h"
and in all imageViews do this.
[imageView setImage:#"default.png"];
[imageView setImageURL:#"whateverurl/whateverimage.png"];
In your case it would be:
[cell.thumbnailImageView setImageURL:#"yourURL"];
It works like a charm, and my code is in production. But if you still want your code to work try this:
UIActivityIndicator *activity =[[UIActivityIndicator alloc] initWithStyle:UIActivityIndicatorWhite];
[activity setFrame:CGRectMake(0,0,30,30)];
[cell.contentView addSubview:activity];
cell.thumbnailImageView.image=[UIImage imageNamed:#"Default~cell~image.png"];
dispatch_queue_t dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(dispatchQueue, ^(void)
{
[activity startAnimating];
[self loadImages];
dispatch_sync(dispatch_get_main_queue(), ^{
NSData *imageUrl = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.content objectAtIndex:indexPath.row] valueForKey:#"imageUrl"] ]];
cell.thumbnailImageView.image=[UIImage imageWithData:imageUrl]; [activity stopAnimating];
[activty setHidden:YES];
});
});
This happens because every time your cell goes off screen your image is released and if you scroll it back on screen you will have to download your image again. Simply cache your image when downloaded and check if exists use it if not download from internet. You can use third party library like SDWebImage GitHub link
Import SDWebImageView+WebCache.h and in your cellForRowAtIndexPath use the following
[cell.thumbnailImageView setImageWithURL:[NSURL URLWithString:[[self.content objectAtIndex:indexPath.row] valueForKey:#"imageUrl"] placeholder:[UIImage imageNamed:#"placeholder.png"]];
use sdwebimage and down load the library file from here
the few steps you do follow
add the sdwebimage in your project after that
in your .h file
#import "UIImageView+WebCache.h"
in your .m file
call the single line in your cellforRowAtIndexPath
[cell.thumbnailImageView setImageWithURL:[NSURL URLWithString:[[self.content objectAtIndex:indexPath.row] valueForKey:#"imageUrl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Use an NSOperationQueue so that you can perform the loading of the data on a background thread.
After that you should set the image on the main queue.
// Assume queue is created
[queue addOperationWithBlock:^{
NSData *imageUrl = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.content objectAtIndex:indexPath.row] valueForKey:#"imageUrl"] ]];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
cell.thumbnailImageView.image=[UIImage imageWithData:imageUrl];
}];
}];
For more about NSOperationQueue see the docs about NSOperationQueue.
So try to load image asynchronous.
https://github.com/nicklockwood/AsyncImageView
Use gcd to populate the images,
NSURL *imageUrl = [NSURL URLWithString:[[self.content objectAtIndex:indexPath.row] valueForKey:#"imageUrl"] ]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
UIImage *image = nil;
image = [UIImage imageWithData: [NSData dataWithContentsOfUrl: imageUrl]];
dispatch_sync(dispatch_get_main_queue(), ^{
cell.thumbnailImageView.image = image;
});
})
You will probably want to store the image to some model object, also track if the download has been initiated, since you would not want to queue up the request for the same image url.
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.
In my application I am parsing JSON data and then displaying that data in UITableView. The information is displayed in the table but the touch response is lagging really bad. I did some research and found out that it is recommended to implement asynchronous loading for the information and especially the image, but I could not find any relevant solutio that worked with my JSON application. I would appreciate some suggestions and comments of how to sort out this problem, here is the code:
jURL Definition www.website.com/info.json
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(jQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:
jURL];
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:NO];
});
}
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary* jsonDict = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
calRes = [jsonDict objectForKey:#"results"];
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *calDict = [calRes objectAtIndex:indexPath.row];
NSURL *imageURL = [NSURL URLWithString:[calDict objectForKey:#"image"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *imageLoad = [[UIImage alloc] initWithData:imageData];
cell.textLabel.text = [calDict objectForKey:#"name"];
cell.detailTextLabel.text = [calDict objectForKey:#"description"];
cell.imageView.image = imageLoad;
return cell;
}
I like to use the AFNetworking library for easy asynchronous image loading. You will need to include the library
#import "AFNetworking.h"
Then use it in the cellForRowAtIndexPath
[cell.imageView setImageWithURL:[NSURL URLWithString:[calDict objectForKey:#"image"]]
placeholderImage:[UIImage imageNamed:#"placeholder"]];
You also need to supply a placeholder image. I use a blank JPG of the size you will want the final image will be.
You can use SDWebImage from this link : https://github.com/rs/SDWebImage
It is the simplest and fastest library for asynchronous image loading.
It also provides image caching.
You can just done the whole operations by simply calling this function:
[cell.imageView setImageWithURL:jURL
placeholderImage:[UIImage imageNamed:#"your place holder here"]];
Just enjoy it.
As a follow up, it will be good to cache the images locally using this very handy plugin by Jake Marsh: JMImageCache
This way, the images will not need to be loaded from the URL the next time you boot the app.
See, the lagging in cellforRowAtIndexPath is because of this
NSURL *imageURL = [NSURL URLWithString:[calDict objectForKey:#"image"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *imageLoad = [[UIImage alloc] initWithData:imageData];
why don't you, use GCD for adding the image? Further more you can have your own NSCache to store the image so that every time the table reloads, the image can be directly loaded from the memory instead of firing the url.