I'm loading the images from URL in UITableView. But it's very slow when loading an view. Here's an example,
UIImage *image = nil;
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://calcuttans.com/palki/wp-content/uploads/2009/02/kidscover-small.png"]]];
In Table view, UIButton i'm setting the background image.
Please Can you provide the sample.
FYI : I'm used the LazzyTable sample program but it's not much helpful. Can you suggest any other samples.
Load image asynchronously
NSURL* url = [NSURL URLWithString:#"http://calcuttans.com/palki/wp-content/uploads/2009/02/kidscover-small.png"];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
NSImage* image = [[NSImage alloc] initWithData:data];
// do whatever you want with image
}
}];
There are some open source libraries available for this:
HJCache
SDWebImage
These libraries download image in a asynchronous manner and cache it for further use.
Try to implement AFNetworking. It uses async requests to download the image, you are currently blocking your view with every download.
You can then use an AFImageRequestOperation to download your image.
if you load the image all download from the internet every time , it must be very slow.
I think you shuold exist your download image to the filePath , and when you will load the image , you can check whether the image has been downloaded before , if not ,then download. if it has been downloaded , you can use imageWithContentsOfFile: method to load the image
//Make use of dispatch queue for faster processing of data. add this in viewDidLoad
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSData * data=[NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
[self performSelectorOnMainThread:#selector(setImage:) withObject:data waitUntilDone:YES];
});
//once data is got set the image and reload tableview
-(void)setImage:(NSData *)responseData
{
image = [UIImage imageWithData:responseData];
[tableView reloadData];
}
maybe you can use asihttprequest to lazy load images. use ASINetworkQueues
You've to use NSOperationQueue to make your tableview efficient.
Check this icodeblog tutorial and raywenderlich tutorial
Have a look at this tutorial. It helped me a lot. When I was using it I was quite new to iOS in general and it was helpful not only with respect to loading images from the web.
http://www.markj.net/iphone-asynchronous-table-image/
With AFNetworking it is more easy.
//AFNetworking
#import "UIImageView+AFNetworking.h"
[cell.iboImageView setImageWithURL:[NSURL URLWithString:server.imagen] placeholderImage:[UIImage imageNamed:#"qhacer_logo.png"]];
Related
I have two views on which images are loading from server.Images are loaded asynchronously.So when loading of images is done i want to call a function or execute a block of code.So how can i create a listener which listen to loading of images. I have three images on view for loading of each image I am using below code to load images from server.
dispatch_async(queue, ^{
NSString *urlString=[IMAGE_BASE_URL stringByAppendingString:bc.logo];
NSLog(#"logo url is %#",urlString);
NSURL *logo_url = [NSURL URLWithString:urlString];
NSData *logo_image_data= [NSData dataWithContentsOfURL:logo_url];
UIImage *logo_imge= [UIImage imageWithData:logo_image_data];
dispatch_async(dispatch_get_main_queue(), ^{
self.img_front_logo.image = logo_imge;
});
});
I want to get notification in my class when loading of all three images is done not for single image.
I am beginner in iOS so don't have any idea about this?
Please use this code
AsyncImageView *asyncimage = [[AsyncImageView alloc]initWithFrame:CGRectMake(4,4,146,146)];
NSString *urlString=[IMAGE_BASE_URL stringByAppendingString:bc.logo];
asyncimage.imageURL=[NSURL URLWithString:urlString];
[backviewright addSubview:asyncimage];
I have implemented an app extension for my application, but i am facing an issue when trying to load an image from a URL into an imageView.
I tried to use PAImageView and UIImageView but both with failure.
The code that i was using for PAImageView is the following:
[self.imageView setImageURL:[NSURL URLWithString:#"https://blabblaLogo.jpg"]];
self.userImageView.clipsToBounds = YES;
and tried to use SDWebImage for UIImageView with the following:
[self.imageView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:#"default.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
}];
and the image doesnt appear in both cases. Note that a default image from assets is displayed correctly without any issue.
Is it possible to load an image from a URL in an app Extension? and how can we achieve that?
Thank you.
Am using something like this and it's work good until this issues fixed
cell.avatar.image = [UIImage imageNamed:#"selection-box_emty.png"];
// Load the image with an GCD block executed in another thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:Arr[indexPath.row][#"avatar"]]];
if (data) {
UIImage *offersImage = [UIImage imageWithData:data];
if (offersImage) {
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *offersImage = [UIImage imageWithData:data];
cell.avatar.image = offersImage;
});
}
}
});
I faced a similar problem, put breakpoints into into library and problem apparently was App Tranport Security. We need separate App Transport Security Settings for every extension we add
Try This in your Image url
If image url contain any space it will add %20 and work fine
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
I am trying to download some thumbnail from server and then display them in each cell :
// displaying image...
dictionary = [newsFeed objectAtIndex:indexPath.row];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[dictionary objectForKey:#"image"]]]];
cell.imageView.image = [image imageScaledToSize:CGSizeMake(55, 55)];
but after downloading and displaying images, the table view scrolls slowly!
The main problem is that [NSData dataWithContentsOfURL:] method is a synchronous request. It blocks the thread where is running until the request is done.
You should avoid this type of interaction if you run this on the main thread. This thread will be frozen and the user will be disappointed ;)
You have many solutions for this. A simple one is to use third library like SDWebImage or AFNetworking.
Both have categories around UIImageView class that allows to use them in a simple manner. For example, using UIImageView+AFNetworking you should do like the following:
[cell.imageView setImageWithURL:yourURL placeholderImage:yourPlaceholderImage];
I think You are trying to say this.
NSURL* url = [NSURL URLWithString:#"http://www.YourImageUrl.com"];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
// Now workout with the image
}
}];
This will make the asynchronous call, and load the images after tableview loaded i.e when the image load complete the image will show but the table will be loaded when the table view is needed to load.
Directly use like this
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[dictionary objectForKey:#"image"]]]];
It takes the main thread, so you can't scroll befor download your Image.So You add NSURLConnectionDataDelegate, NSURLConnectionDelegate add this protocol and download image by
Insert these lines of coding where you want to download Your Image
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
received_data = [[NSMutableData alloc]init];
[connection start];
These lines triggers these delegates to download data.
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[received_data setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[received_data appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Use your download image
imageView.image = [UIImage imageWithData:received_data];
}
Using AFNetworking will get you a better feel. There is a UIImageView category as part of the project that will insert a temporary image, while switching to a background thread to download the real image.
That will keep the image download from locking the main thread. Once the image is downloaded the temporary image will be swapped out for you.
Here's a nice tutorial that includes some pointers on using the UIImageView category AFNetworking crash course.
I have written an answer here:
https://stackoverflow.com/a/14624875/1375695
which explains how to use Grand Central Despatch to keep your table scrolling smoothly while your images are downloading in the background. That answer doesn't mandate the use of a 3rd party library. Although - as Andrew and Flexaddicted have mentioned - there are libraries which will provide a solution for you - it might be worth reading so that you can understand what needs to happen under the hood.
Note that in my proposed solution, you could still use your synchronous method to actually get the data from the network:
UIImage *image = [UIImage imageWithData:
[NSData dataWithContentsOfURL:
[NSURL URLWithString:
[dictionary objectForKey:#"image"]]]];
as it would be called on an asynchronous background thread.
I highly recommend the AFNetworking framework as #flexaddicted has recommended (UIImageView+AFNetworking). Also, check out the Sensible TableView framework. It should be able to automatically fetch all data from the web service and display them in the table view, and will also automatically handle all asynch image downloading. Should save you a bunch of work.
For More convenience to download image use EGOImageLoader/EGOImageView
Download this class by this link
https://github.com/enormego/EGOImageLoading
I've been researching and haven't found any answer to this question - sendAsynchronousRequest vs. dataWithContentsOfURL.
Which is more efficient? more elegant? safer? etc.
- (void)loadImageForURLString:(NSString *)imageUrl
{
self.image = nil;
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError)
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if (data) {
self.image = [UIImage imageWithData:data];
}
}];
}
OR
- (void)loadRemoteImage
{
self.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSData * imageData = [NSData dataWithContentsOfURL:self.URL];
if (imageData)
self.image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
if (self.image) {
[self setupImageView];
}
});
});
}
So I've come up with an answer for my own question:
Currently there are 3 main ways to load images async.
NSURLConnection
GCD
NSOperationQueue
Choosing the best way is different for every problem.
For example, in a UITableViewController, I would use the 3rd option (NSOperationQueue) to load an image for every cell and make sure the cell is still visible before assigning the picture. If the cell is not visible anymore that operation should be cancelled, if the VC is popped out of stack then the whole queue should be cancelled.
When using NSURLConnection + GCD we have no option to cancel, therefore this should be used when there is no need for that (for example, loading a constant background image).
Another good advice is to store that image in a cache, even it's no longer displayed, and look it up in cache before launching another loading process.
sendAsynchronousRequest is better, elegant and whatever you call it. But, personally, I prefer creating separate NSURLConnection and listen to its delegate and dataDelegate methods. This way, I can: 1. Set my request timeout. 2. Set image to be cached using NSURLRequest's cache mechanism (it's not reliable, though). 2. Watch download progress. 3. Receive NSURLResponse before actual download begins (for http codes > 400). etc... And, also, it depends on cases like, image size, and some other requirements of your app. Good luck!
I need you to humor me during this question. This is somewhat pseudo code because the actual situation is quite complex. I wouldn't load an image this way unless I needed to. Assume that I need to.
NSURL *bgImageURL = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo3w.png"];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:bgImageURL]];
[self.anIBOutletOfUIImageView setImage:img];
but I crash out with
-[__NSCFData _isResizable]: unrecognized selector sent to instance 0x9508c70
How can I load an image from a URL into NSData and then load that NSData into a UIImage and set that UIImage as the image for my UIImageView?
Again, I realize this sounds like nonsense, but due to an image caching system I'm using I have to do things this way :(
How I usually handle this situation (not compiled, not tested):
NSURL * url = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo3w.png"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse * resp, NSData * data, NSError * error) {
// No error handling - check `error` if you want to
UIImage * img = [UIImage imageWithData:data];
[self.imageView performSelectorOnMainThread:#selector(setImage:) withObject:img waitUntilDone:YES];
}];
This avoids the long-running network request implied by the call to dataWithContentsOfURL:, so your app can continue doing things on the main thread while the data downloads for the image.
As a side note, you seem to be running into the same error as this question; you might want to check that you're not running into object allocation problems.
I plugged this code into a new, iPad "Single view application" template:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSURL *bgImageURL = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo3w.png"];
NSData *bgImageData = [NSData dataWithContentsOfURL:bgImageURL];
UIImage *img = [UIImage imageWithData:bgImageData];
[[self Imageview] setImage:img];
}
I got the image to load up properly. I even tried different content modes for the UIImageView, and they all worked as expected.
If you start from scratch, do you get the same problem?
The error message indicates that you're sending a message of "_isResizable" to an NSData object. Maybe you're inadvertently setting the UIImageView's image property equal to the NSData instead of the UIImage.
Edit/Update
I even went back and tried different versions of "one-lining" the code to see if any of that mattered, since my "working" copy was slightly altered from your non-working copy. I couldn't get the code to break. My guess would be that the code in question isn't broken, but something nearby is...