jesses.co.tt
jesses.co.tt

Reputation: 2729

Get ImageView Image Original Size

I have a TableViewCell with an ImageView, and I am setting the image like so:

[self.contentImageView setImageWithURL:thumbnail_url];

The contentMode is set to UIViewContentModeScaleAspectFill, and the subviews are clipped. This works best for images that are either Portrait or Landscape, but UIViewContentModeScaleToFill actually works better for Landscape images, which are far more plentiful.

So, I want to detect the orientation of the image by comparing the width and height, and change the contentMode accordingly.

At first, I tried to inspect/log the ImageView.image property, directly after I set it from the url, but it show's nil. not sure why exactly...?

Next, I decided to put that NSURL into an NSData object, then create an UIImage from that data, and set the ImageView's image property with that iVar, like so:

NSData *data = [NSData dataWithContentsOfURL:thumbnail_url];
UIImage *image = [UIImage imageWithData:data];
[self.contentImageView setImage:image];
// Get image.size etc.

This - particularly the NSData call - slows down the loading of the TableViewCell's considerably, so I'd like to avoid it.

So, I'm wondering if there is anyway to reach into the un-cropped source image properties of the ImageView before the scaling happens to the contentMode?

Upvotes: 1

Views: 393

Answers (1)

Dima
Dima

Reputation: 23634

The problem here is your misunderstanding of how that first method works. setImageWithURL: is a method from one of the open source image loading libraries. Probably either AFNetworking or SDWebImage.

These methods are asynchronous and return immediately. They download the image on a background queue and then return to the main queue to set up the view with it. You are trying to access the image before it is downloaded. The reason the manual NSData approach is working is because it is synchronous and the main queue is stuck while the images download.

Both libraries I mentioned have separate methods with a callback block on the main queue allowing you to act on the response.

For AFNetworking you can use this method:

- (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
              placeholderImage:(UIImage *)placeholderImage
                       success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image))success
                       failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error))failure;

For SDWebImage you can use this method:

- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;

In either of these, the callback blocks will let you access the image once it is downloaded (if successful).

You can also make something like this work manually using the dataWithContentsOfURL: approach by using GCD like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^()
               {
                   NSData *data = [NSData dataWithContentsOfURL:thumbnail_url];
                   UIImage *image = [UIImage imageWithData:data];
                   dispatch_async(dispatch_get_main_queue(), ^()
                                  {
                                      [self.contentImageView setImage:image];
                                  });
               });

This is a basic pattern used in networking to perform the network request and processing on a background queue before updating the view on the main queue. Keep in mind this particular piece of code is very simplistic and would require more work to work as nicely as the libraries I mentioned above.

Upvotes: 2

Related Questions