AFNewtorking loading images from Amazon S3 - ios

We were using AFNetworking only to load images like this:
[thumbnailImage setImageWithURL:_item.thumbnailUrl];
and it worked fine. But now we've pulled in the rest of the project it has stopped working. It was just showing the background color. So I tried using this and it loads the placeholder but never loads the image.
UIImage* placeholder = [UIImage imageNamed:#"placeholder"];
[thumbnailImage setImageWithURL:_item.thumbnailUrl placeholderImage:placeholder];
I thought I might be able to see what the problem was so I tried:
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:_item.thumbnailUrl cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30];
[thumbnailImage setImageWithURLRequest:urlRequest placeholderImage:[UIImage imageNamed:#"placeholder"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image)
{
NSLog(#"Loaded Image");
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
{
NSLog(#"Failed to load Image");
}];
and it seems that it's not getting the return type that it's expecting. It says Expected content type image/png, got binary/octet-stream I'm pulling the image from Amazon S3 so I don't know if I have control over the type.

I wasn't able to change the data type so I overrode the acceptableContentTypes method in AFNetworking by adding the following files to my project.
AFImageRequestOperation+OctetMIMEType.h
//
// AFImageRequestOperation+OctetMIMEType.h
// iQ.fileShare
//
// Created by Poole, Patrick on 4/25/13.
//
//
#import "AFImageRequestOperation.h"
#interface AFImageRequestOperation (OctetMIMEType)
#end
AFImageRequestOperation+OctetMIMEType.m
//
// AFImageRequestOperation+OctetMIMEType.m
// iQ.fileShare
//
// Created by Poole, Patrick on 4/25/13.
//
//
#import "AFImageRequestOperation+OctetMIMEType.h"
#implementation AFImageRequestOperation (OctetMIMEType)
+ (NSSet *)acceptableContentTypes {
return [NSSet setWithObjects:#"binary/octet-stream",#"image/tiff", #"image/jpeg", #"image/gif", #"image/png", #"image/ico", #"image/x-icon" #"image/bmp", #"image/x-bmp", #"image/x-xbitmap", #"image/x-win-bitmap", nil];
}
#end

AFNetworking provides a method to add acceptable content types in 1.3.3, I'm not sure what other versions support this
[AFImageRequestOperation addAcceptableContentTypes:[NSSet setWithObjects:#"binary/octet-stream", nil]];

Related

How to load images using SDWebImage library

Hi I am using SDWebImage for loading images ok that's fine
Here I am getting images from services and I want to resize those images and I want to load them using SDWebImage
for this I wrote the code below
Obj.imageYH---> this is imageURL
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:Obj.imageYH]];
UIImage *actualImage = [UIImage imageWithData:imageData];
UIGraphicsBeginImageContext(CGSizeMake(150, 150));
[actualImage drawInRect:CGRectMake(0,0,150, 150)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *smallData = UIImagePNGRepresentation(newImage);
NSString *Finalstring = [[NSString alloc] initWithData:smallData encoding:NSUTF8StringEncoding] ;
[Mainimage sd_setImageWithURL:[NSURL URLWithString: Finalstring] placeholderImage:[UIImage imageNamed:#"collectionViewIcon.png"]];
but in the code above, I am getting null value in Finalstring. How can I resize it and how can I load images using SDWebImage?
Step 1: Installation of SDWebImage
To start with, make sure you're using the latest version of SDWebImage, and installed via CocoaPods (not recommend to link up the library manually).
Your Podfile should contain this line:
pod 'SDWebImage', '~>3.7'
After that, close the Xcode project and run pod install in your project directory. Use the Xcode workspace after installation.
Step 2: Using the codes
First of all, you have the import the library
#import <SDWebImage/UIImageView+WebCache.h>
At this moment, try to Clean & Build the Workspace. If everything goes well, the project should be built without error.
Then, in your function:
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:Obj.imageYH
options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
// progression tracking code, optional.
// You can set the progress block to nil
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (image) {
// Resize your image here, then set it to UIImageView
Mainimage.image = [UIImage imageWithData:UIImagePNGRepresentation(image) scale:0.5f];
// resize to 0.5x, function available since iOS 6
}
}];
done.
Use below line of codes instead of your code :
UIImage *actualImage = [UIImage imageWithData:imageData];
UIGraphicsBeginImageContext(CGSizeMake(150, 150));
[actualImage drawInRect:CGRectMake(0,0,150, 150)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *smallData = UIImagePNGRepresentation(newImage);
[smallData writeToFile:Finalstring atomically:YES];// Finalstring is file path of resize image
[Mainimage sd_setImageWithURL:[NSURL URLWithString: Finalstring] placeholderImage:[UIImage imageNamed:#"collectionViewIcon.png"]];
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:url delegate:self options:0 success:^(UIImage
*image) {
cell.profilePicture.image = [self imageByScalingAndCroppingForSize:CGSizeMake(cell.profilePicture.frame.size.width,
cell.profilePicture.frame.size.height) image:image]; } failure:nil];
Don't forget to include
#import <SDWebImage/UIImageView+WebCache.h>
#interface YourViewController : UIViewController <SDWebImageManagerDelegate>

afnetworking downloading an array of images

I am trying to download an array of images, but I never receive the image callback:
for (int i = 0; i < self.apartments.count; i++) {
NSLog(#"downloading another image");
ATProperty *aProp = self.apartments[i];
if (aProp.aptImages.count > 0) {
NSURL *url = [NSURL URLWithString:aProp.aptImages[0]];
NSLog(#"url string: %#", aProp.aptImages[0]);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
UIImage *placeholderImage = [UIImage imageNamed:#"loading_apt.png"];
UIImageView *anotherImage;
NSLog(#"about to start req");
[anotherImage setImageWithURLRequest:request
placeholderImage:placeholderImage
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image)
{
NSLog(#"got an IMAGE ");
self.imagesArray[i] = image;
if (self.apartments[0] == aProp) [self setupDraggableView:image];
} failure:nil];
} else {
UIImage *defImage = [UIImage imageNamed:#"default_apt.png"];
if (self.apartments[0] == aProp) [self setupDraggableView:defImage];
[self.imagesArray addObject:defImage];
}
}
As you can see, I don't actually want to set an imageview, I just want to put the UIImage into an array for later use. In this case, the "got an IMAGE" log statement is never received. Why would this be the case? The url is valid. Also, is this somewhat like a javascript closure? For example if I have a total of 5 apartments in the array, when I do the first callout (i = 0) and get the success callback will i be the value in which the callout was instantiated (i.e. 1)?
anotherImage is nil, so it never loads. try like that:
UIImageView *anotherImage = UIImageView.new;

iOS App - Display images in a grid view froma list of JSON URL.

I'm storing a list of URLs in a MYSQL db table and I have been able to successfully retrieve the URLS via JSON.
However, now that I have the JSON I am not sure how to display the images in a image gallery type view in my iPhone App.
What I plan on having is a huge list of URL's to image in the database and I want to display x amount at a time and then once the user scrolls to the end I want to display x amount more. Like pinterest.
Any hints?
#import "mySQLAppViewController.h"
#interface mySQLAppViewController (){
}
- (IBAction)loadJSON:(id)sender;
#end
#implementation mySQLAppViewController
- (IBAction)loadJSON:(id)sender {
NSString *dataUrl = [NSString stringWithFormat:#"http://MYDOMAIN.com/results.php"];
NSURL *url = [NSURL URLWithString:dataUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
for (int i =0 ; i < [JSON count]; i++) {
//NSString *image_url = JSON[i][#"image_url"];
//NSLog(#"%#", image_url);
//^^THIS SUCESSFULLY LOGS THE URL LINKS (I.E. HTTP://MYDOMAIN.COM/CAR.JPG)
NSURL *imageURL = [NSURL URLWithString:JSON[i][#"image_url"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
}
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Error Retrieving Weather"
message:[NSString stringWithFormat:#"%#",error]
delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
}];
[operation start];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Sounds like you want to look at UICollectionView. Here's a tutorial to get you started:
Beginning UICollectionView In iOS 6.
Edit: Edited after davidm's answer to be more complete: (https://stackoverflow.com/a/16918758/412339) Mark his as answer if it (UICollectionView) is the best for your solution.
iOS 6 and above:
You should really check out UICollectionView. A really good resource for this is found here: Create an iOS 6 UICollectionView Using Storyboards
iOS 5 and lower:
One thing that you can do is create a custom ViewController that has an array of your image URLs or your JSON Array:
#property (nonatomic, retain) NSArray *imageURLs;
Then create a set of reusable UIImageViews (which is another question in itself, but basically you need an array that holds custom UIImageViews with a reuse identifier, similar to a UITableViewCell).
#property (nonatomic, retain) NSArray *imageViews;
Finally, you will need a UIScrollView and UIView (to contain the UIImageViews) that watches the position and adds the imageview on the screen using a UIScrollViewDelegate method (scrollViewDidScroll: should work).
Alternatively, you can just implement a UITableViewController and Delegate with a custom UITableViewCell and let Apple's engineers take care of most of that for you, but you won't be able to put photos side by side, only stacked on top of each other. That may be what you are wanting though.

AFNetworking setImageWithURLRequest not setting remote image

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.

Table view with image caching and "pull to update" option

Almost every ios app now has something like "Feed" option.
Programming that usually includes fetching images from the web, caching them, handling pages, "pull to update option", etc. - all the standart stuff.
But looks like there is no standart solution for that?
I tried "three 20" - really big, complicated library with many modules. It really lacks good documentation! And it also had "slowdowns" while fetching images from cache.
Maybe I should use different small libraries for each small task separately? Like HJCache, EGO, etc.
Or is it better to write everything from scratch without any libraries?
Please give me advice on best practices here, i am really stuck now.
This one is very easy to drop in for pull to refresh.
For image loading, I wrote the following category for UIImageView:
// .h
#interface UIImageView (UIImageView_Load)
- (void)loadFrom:(NSURL *)url completion:(void (^)(UIImage *))completion;
#end
// .m
#import "UIImageView+Load.h"
#import <QuartzCore/QuartzCore.h>
#implementation UIImageView (UIImageView_Load)
- (void)loadFrom:(NSURL *)url completion:(void (^)(UIImage *))completion {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data) {
self.image = [UIImage imageWithData:data];
if (completion) completion(self.image);
}
}];
}
#end
// To use it when building a cell
//...
MyModelObject *myModelObject = [self.myModel objectAtIndex:indexPath.row];
if (myModelObject.image) {
cell.imageView.image = myModelObject.image;
} else {
NSURL *url = [NSURL urlWithString:myModelObject.imageUrl];
[cell.imageView loadFrom:url completion:^(UIImage *image) {
// cache it in the model
myModelObject.image = image;
cell.imageView.image = image;
}];
}
// ...
I'm a fan of Leah Culver's Pull to Refresh library, or this STableViewController which handles pull-to-refresh as well as endless scrolling downward.
For image loading, try SDWebImage from the DailyMotion app.

Resources