AFNetworking setImageWithURLRequest not setting remote image - ios

I'm using AFNetworking's UIImageView+AFNetworking.h to asynchronously load an online image onto a UIImageView.
The remote image loads very well when I use setImageWithURLRequest:, but when I try using setImageWithURLRequest:placeholderImage:success:failure the remote image is downloaded but the UIImageView does not set it as its UIImage.
Here's my code:
#property (strong) IBOutlet UIImageView *imageView;
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[_imageView setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://i.imgur.com/fVhhR.png"]]
placeholderImage:nil
success:^(NSURLRequest *request , NSHTTPURLResponse *response , UIImage *image ){
NSLog(#"Loaded successfully: %d", [response statusCode]);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
NSLog(#"failed loading: %#", error);
}
];
}
Image always loads successfully, the status code is always 200. But I have to add [_imageView setImage:image]; to the success block for the UIImageView to set the image.
I'm using iOS 6.0
Any ideas?

If you supply a success block then you are responsible for setting the image property of your UIImageView. If you supply a nil success block then AFNetworking does it for you.
This is the relevant section of UIImageView+AFNetworking.m (line 117):
if (success) {
success(operation.request, operation.response, responseObject);
} else {
self.image = responseObject;
}
Alternatively, just use the -setImageWithURL:placeholderImage: without the completion blocks.

I had the same problem and after being frustrated with the docs for the library I found what Robin mentioned above. So now I'm using:
[imageView setImageWithURLRequest:imageRequest placeholderImage:nil success:nil failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Unable to retrieve image");
}];
Works like a charm. I hope this helps.

The doc is very clear:
If a success block is specified, it is the responsibility of the block
to set the image of the image view before returning. If no success
block is specified, the default behavior of setting the image with
self.image = image is applied.
So you can either pass a nil block for success (as mentioned above) or call setImage:image yourself if you specify a block

In your success block, you need to give the UIImaage *image to your UIImageView. I assuming you are getting the NSLog(#"Loaded successfully: %d", [response statusCode]);
Also, it appears your placeholder image is nil. Don't you want a placeholder like a loading image in there?

For those who has stumbled upon this issue and got here while browsing and searching on the web, here's an another reason - the image might have wrong file extension. For example, the image might be saved as jpg, but someone has decided to change its file extension to png.
Here's how to check that: first you need to use your network monitoring tool (for example Charlie) and check image request "Content-Type" HTTP header. Suppose, it has value "image/png". This means the image on the backend has png file extension. Now, run your app on simulator, then go to simulator folder of your app:
/Users/you/Library/Application Support/iPhone simulator/select-folder-with-your-iOS-version/Applications/YourApp/Library/Caches/yourAppBundleId/fsCachedData/
Find your image file and add png or jpg extension to this file (AFNetworking caches image files without file extension, so need to add it in order to open it with Preview). Open it with Preview and press Tools/Show Inspector. Check for "Document Type" in the opened panel. If it's different than "PNG image" (for example JPEG image) then that's the cause and you need to fix the image itself on the backend - open it with appropriate image editing program and save it as PNG.

Related

Images in UIWebView doesn't scaleToFit in iOS 10.3.1

I have an image which I'm loading in a UIWebView. I've set the scaleToFit as YES for webView. Still it doesn't scale to the screen of webView.
This is happening only when I'm running it on iOS 10.3.1. It work fine on older versions.
self.webView.scalesPageToFit = YES;
Have you placed any constraints on the image? It could be to do with the device size rather than the iOS version?
Just a thought, might be completely wrong...
May I ask why you load an image into a UIWebView in the first place?
I recommend using UIImageView whenever possible. With this, you can set it's "contentMode" to your preferred setting. If you need a way to load remote images, check out this really popular & easy to use library:
https://github.com/rs/SDWebImage
With the above library loading a remote image is as easy as this:
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:iconURL] options:SDWebImageDownloaderHighPriority progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
dispatch_async(dispatch_get_main_queue(), ^{
[yourImageView setImage:image];
});
}];

Remotely Loading Images in an iPhone App

An app that I am making will contain mass amounts of images. So obviously it would be really bad to store them all on the users phone and take up all the disk space. As I am new to iOS Development, how would I best go about loading an image remotely into a UIImageView. What are my options?
Just to let you know I would only ever be loading a maximum of 2 images at a time, if it helps.
Any advise would be very much appreciated. Thank you in advance!
You can download image Asynchronously by unblocking the main thread using the below code
NSURLRequest* request=[NSURLRequest requestWithURL:[NSURL URLWithString:#"Your imageURL"]];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if (error==nil && [data length]>0)
{
UIImage* img=[UIImage imageWithData:data];
// set the downloaded image to imageview here
}
else
{
NSLog(#"%#",error);
}
});
Use SDImageView or similar open sources, another options if you are loading images in table, use Lazy Loading by Apple

UITableView scrolls slow after downloading cell images

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

Slow loading the images from URL in UITAbleView.

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"]];

ios awkard image loading (url to nsdata to uiimage to uiimageview)

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...

Resources