UIImageView retained stronly in UIScrollView - ios

I have cobbled together some methods to resize images and put them into a UIScrollView for horizontal scrolling, however one of my problems is that I'm capturing strongly, and I have attempted a few options that I have read about, but all result in no images being displayed. I'm hoping one of you can help me resolve this issue so I can quit cooking so much memory when my app loads the images into the scroll view.
- (void)setImage:(NSURL *)imageURL errorImage:(UIImage *)errorImage{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imageURL];
[request addValue:#"image/*" forHTTPHeaderField:#"Accept"];
UIImageView *newView = [[UIImageView alloc] initWithFrame: CGRectMake(self.x, 0, self.screenWidth, self.screenHight)];
[self.scrollView addSubview: newView];
self.x = (self.x + newView.frame.size.width);
if(self.x > self.view.frame.size.width) {
self.scrollView.contentSize = CGSizeMake(self.x, self.scrollView.frame.size.height);
}
[[newView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)]; // Remove previous that not stop
__block UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] init];
activityIndicator.frame = newView.bounds;
[activityIndicator setHidden:NO];
[activityIndicator startAnimating];
activityIndicator.color = [UIColor redColor];
[newView addSubview:activityIndicator];
void (^removeSpinner)(void) = ^{ // Desctuctor Block
if (activityIndicator) {
[activityIndicator setHidden:YES];
[activityIndicator stopAnimating];
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}
};
[newView setImageWithURLRequest:request placeholderImage:nil success: ^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
removeSpinner();
// resize the resulting image for this device
newView.image = [self imageScaleCropToSize:image];
NSLog(#"successfully loaded image: %#", imageURL);
} failure: ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
removeSpinner();
NSLog(#"failed loading [%#]: %#", imageURL, error);
}];
}

Related

AFNetworking:Asynchronous image download using setImageWithURLRequest

I have a image slider and am downloading images from url using setImageWithURLRequest. Suppose a user slide from left to right as soon as app code then I have to show the rightmost index image which I can achieve but after that I have to download images from beginning of the index. How to achieve that?
for (int i = 0; i < self.items.count; i++) {
CGRect frame;
frame.origin.x = scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
UIView *subview = self.view;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.contentMode = UIViewContentModeCenter;
subview = imageView;
NSURLRequest *imagerequest = [NSURLRequest requestWithURL:[_items objectAtIndex:i]];
__weak UIImageView *weakImageView = (UIImageView *) subview;
[(UIImageView *) subview setImageWithURLRequest:imagerequest
placeholderImage:[UIImage imageNamed:#"placeholder.gif"]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
UIImageView *strongImageView = weakImageView; // make local strong reference to protect against race conditions
if (!strongImageView) return;
strongImageView.image = image;
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
//[activityIndicatorView removeFromSuperview];
// do any other error handling you want here
}];
[scrollView addSubview:subview];
}
U can use UIImageView+AFNetworking.h:
- (void)setImageWithURL:(NSURL *)url
placeholderImage:(UIImage *)placeholderImage;
Example:
[imageView setImageWithURL:<url> placeholderImage:<image>];
Or:
- (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;
Example:
[imageView setImageWithURL:<url> placeholderImage:<image> success:<successBlock> failure:<faliureBlock>];

How to asynchronously download images in ios?

I want to first create imageview onto the scroll view.there i set placeholder image or give Background color of imageview.so all image view are display.
- (void)LoadDataInScrollView
{
dispatch_queue_t imageQueue = dispatch_queue_create("Image Queue",NULL);
//totalImageGetDict into count total Number of object and generate imageview.
for (int ivalue = 0; ivalue < [totalImageGetDict count]; ivalue++)
{
dispatch_async(imageQueue, ^{
//define x value
CGFloat xOrigin =ivalue *ascrollView.frame.size.width+50;
imageView = [[UIImageView alloc] init];
imageView.tag = ivalue;
[imageView setBackgroundColor:[UIColor whiteColor]];
imageView.frame = CGRectMake(xOrigin-40,imgYpos, ascrollView.frame.size.width-20, scrollViewHight);
//then here first i set already downloaded image.it's comes from another class. getImageLoadDict into images are already downloaded**
if ([getImageLoadDict objectForKey:[NSNumber numberWithInteger:ivalue]]!= nil)
{
//dispatch_async(dispatch_get_main_queue(), ^{
[imageView setImage:[getImageLoadDict objectForKey:[NSNumber numberWithInteger:ivalue]]];
//});
}
else
{
//totalImageGetDict into remaining images object and asynchronously download here.
STVisionPhoto *photoObj = [totalImageGetDict objectForKey:[NSNumber numberWithInteger:ivalue]];
UIImage *newimage = [photoObj image];
dispatch_async(dispatch_get_main_queue(), ^{
[imageView setImage:newimage];
});
}
[ascrollView addSubview:imageView];
});
}
}
You can use SDWebImage to do it.It is pretty easy to use
Edit :
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage * image = [UIImage imageWithData:[NSData dataWithContentsOfURL:your url]];
dispatch_async(dispatch_get_main_queue(), ^{
[imgview setImage:image];
});
});
You can try this if you don't want to use any library
Try to use this code:
UIImageView *imgView = [[UIImageView alloc] init];
imgView.frame = CGRectMake(12.5, 12.5, 80, 80);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *profileImage;
profileImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:YOUR_URL_STRING]]];
dispatch_async(dispatch_get_main_queue(), ^{
imgView.image = profileImage;
});
});
[cell.contentView addSubview:imgView];
(void)loadImg:(NSString *)url img :(UIImageView *)imgView{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
__weak UIImageView *imageV = imgView;
[imgView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"songRecDef"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
imageV.image = image;
[imageV setNeedsLayout];
NSLog(#"%#",response);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
[imageV setImage:[UIImage imageNamed:#"songRecDef"]];
NSLog(#"%#",error);
}];
}

drawRect and AFNetworking

I'm using the following code
self.imageView = [[UIImageView alloc] init];
[self.imageView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:#"profile-image-placeholder"]];
[self setNeedsLayout];
[self setNeedsDisplay];
but in drawRect can't see the image only the placeholder using the following
[self.imageView.image drawAtPoint:CGPointMake(15.0f, 5.0f)];
any ideas on this?
I think all you need to do is this. AFNetworking will cancel the image operation if the cell is reused so you don't need to worry about that edge case.
[self.imageView setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] placeholderImage:[UIImage imageNamed:#"profile-image-placeholder"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
self.imageview.image=image;
[self setNeedsLayout];
[self setNeedsDisplay];
} failure:nil];

ios. ScrollView only showing one subview with image

I have a UIScrollView that I want to load a list of images from flickr. Then I want the photos to be displayed like that of the native stock iphone photo app where you scroll through the photos.
Here is my code
- (void)viewDidLoad
{
[super viewDidLoad];
for (int i = 0; i < self.urlArray.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[self returnImageFromFlickr:[self.urlArray objectAtIndex:i]];
UIImageView *imageView = self.largePhoto;
[subview addSubview:imageView];
[self.scrollView addSubview:subview];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.urlArray.count, self.scrollView.frame.size.height);
}
-(void)returnImageFromFlickr:(NSURL *)url {
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[self.largePhoto setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"placeholder.png"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[self.largePhoto setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
}
What is happening only the last image is being shown.
I tried your solution as I understood it and got this. This is not brining up a photo. Just a white screen. Plus a warning in the returnImageFromFlicrk method at
[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
saying
Capturing 'imageView' strongly in this block is likely to lead to a retain cycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
/*for (int i = 0; i < self.urlArray.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[self returnImageFromFlickr:[self.urlArray objectAtIndex:i]];
UIImageView *imageView = self.largePhoto;
[subview addSubview:imageView];
//subview.backgroundColor = [colors objectAtIndex:i];
[self.scrollView addSubview:subview];
}*/
for (int i = 0; i < self.urlArray.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIImageView *imageView = [[UIImageView alloc] init];
[self returnImageFromFlickr:[self.urlArray objectAtIndex:i] imageview:imageView];
[self.scrollView addSubview:imageView];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.urlArray.count, self.scrollView.frame.size.height);
}
-(void)returnImageFromFlickr:(NSURL *)url imageview:(UIImageView *)imageView {
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"placeholder.png"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
}
You are not setting right parameters to the Scroll content pan that is why all the images you want are not displaying in scrollView. Try updating ScrollView's content pan to fit the width of all images. Like
self.scrollView.contentSize = CGSizeMake(Width, Height);
in this case height will be the hight of single image and width will be (width of single image * total number of images)
You overwrite self.largePhoto, you need set your imageView in returnImageFromFlickr
try this
UIImageView *imageView = [[UIImageView alloc] init];
[self returnImageFromFlickr:[self.urlArray objectAtIndex:i] imageview:imageView];
and
-(void)returnImageFromFlickr:(NSURL *)url imageview:(UIImageView *)imageView {
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"placeholder.png"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
[imageView setImage:image];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
}
All I needed to do was move the code from viewDidLoad to viewDidApear

Show UIActivityIndicator with AFNetworking SetImageWithURL

I'm using the AFNetworking library to set images with the contents of URLs. In the following example topLeftImage is an instance of a UIImageView.
[topLeftImage setImageWithURL:[NSURL URLWithString:imageURL]];
What I'd like to do is to show a UIActivityIndicatorView while the image is downloading. However I can't figure where to trigger the starting and stopping of the activity indicator. The following is my code for the activity indicator.
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[topLeftImage addSubview:activityIndicator];
[activityIndicator startAnimating];
How can I link the above code to the setImageWithURL method so that activity indicator appears only while the image is downloading?
UIImageView+AFNetworking.h category provides a setImageWithURL method that allows you to use success and failure blocks. This blocks will be executed once the request finishes in success or fail. So you can start the animation just before the request and put the stop in success and fail blocks. This is a sample code:
NSURL *imageURL = [NSURL URLWithString:#"http://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/402px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg"];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageURL];
[_activityIndicator setHidden:NO];
[_activityIndicator startAnimating];
[_imageView setImageWithURLRequest:imageRequest
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image)
{
[_activityIndicator setHidden:YES];
[_activityIndicator stopAnimating];
_imageView.image = image;
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
{
[_activityIndicator setHidden:YES];
[_activityIndicator stopAnimating];
}];
Simple extension for UIImageView in Swift:
extension UIImageView {
func setImageWithString(string: String?) {
if let string = string, let url = NSURL(string: string) {
let activityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame)))
activityIndicatorView.hidden = false
activityIndicatorView.color = UIColor.lightGrayColor()
addSubview(activityIndicatorView)
bringSubviewToFront(activityIndicatorView)
activityIndicatorView.startAnimating()
setImageWithURLRequest(NSURLRequest(URL: url), placeholderImage: nil, success: { request, response, image in
self.image = image
activityIndicatorView.hidden = true
activityIndicatorView.stopAnimating()
activityIndicatorView.removeFromSuperview()
}, failure: { request, response, error in
activityIndicatorView.hidden = true
activityIndicatorView.stopAnimating()
activityIndicatorView.removeFromSuperview()
})
}
}
}

Resources