Set an image to many UIImageViews - ios

Say I have 60-70 UIImageViews and I want to dynamically load the same image into all of them at the same time (so to speak).
For example, if I were working on a web page with 60-70 divs and I wanted to give them all a background image I would give them all a class of myDivs and call `$('.myDivs').css('background-image', 'url(' + imageUrl + ')');
I know how to set a UIImageView's image but is there an easy way to set a bunch at once in Objective C?
I did try searching but I was flooded with a ton of stuff that is really unrelated.

It depends on the way you wish to display the imageView(s).
If you are using a UITableView or a UICollectionView, in the cellForRowAtIndexPath: method you can dynamically update an imageView placed in a cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
[self setCell:cell forIndexPAth:indexPath];
return cell;
}
- (void)setCell:(UITableViewCell *)cell forIndexPAth:(NSIndexPath *)indexPath
{
__weak UITableViewCell *weakCell = cell;
// 5. add picture with AFNetworking
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:#"www.facebook.com/profileImageLocation"]];
[cell.profileImage setImageWithURLRequest:request
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
weakCell.profileImage
.image = image;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"bad url? %#", [[request URL] absoluteString]);
}];
}
Another option will be using a for loop like this:
- (void)addImagesToAllMyImageViews:(NSArray *)images
{
for (id obj in images) {
if ([obj isKindOfClass:[UIImageView class]]) {
UIImageView *imageView = (UIImageView *)obj;
imageView.image = [UIImage imageNamed:#"someImage.png"];
}
}
}

I think you can do with tag property, select all ImageView and give them a teg like 777 and
for(id* subview in self.view.subview) {
if([subview isKindaOfclass:[UIImageView class]] && (subview.tag == 777)) {
UIImageView* imageView = (UIImageView*)subview;
imageVIew.image = youImage;
}
}
hope this helps you

Related

How to download 100 images from server in Objective-C using NSURLSession

I am making an app..
I need to download many pictures from a server, but I don't know how to do
previously am doing this by following some articles
currently am facing some issues
when scrolling images flicker and change all the time. When scrolling back up fast, all images are wrong. What can I do about that?
- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( !error )
{
UIImage *image = [[UIImage alloc] initWithData:data];
completionBlock(YES,image);
} else{
completionBlock(NO,nil);
}
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"venue";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
Venue *venue = ((Venue * )self.venues[indexPath.row]);
if (venue.userImage) {
cell.imageView.image = venue.image;
} else {
// set default user image while image is being downloaded
cell.imageView.image = [UIImage imageNamed:#"default.png"];
// download the image asynchronously
[self downloadImageWithURL:venue.url completionBlock:^(BOOL succeeded, UIImage *image) {
if (succeeded) {
// change the image in the cell
cell.imageView.image = image;
// cache the image for use later (when scrolling up)
venue.image = image;
}
}];
}
}
**Any best way suggestions **
I see a few issues in your code so let me first give an example of minimum you need:
- (void)downloadImageFrom:(NSURL *)path completion:(void (^)(UIImage *image))completionBlock {
dispatch_queue_t queue = dispatch_queue_create("Image Download", 0);
dispatch_async(queue, ^{
NSData *data = [[NSData alloc] initWithContentsOfURL:path];
dispatch_async(dispatch_get_main_queue(), ^{
if(data) {
completionBlock([[UIImage alloc] initWithData:data]);
} else {
completionBlock(nil);
}
});
});
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = ...; // Create my own cell
NSString *imageURL = ...; // Get from my model
cell.imageURLString = imageURL;
[self downloadImageFrom:[NSURL URLWithString:imageURL] completion:^(UIImage *image) {
if(cell.imageURLString == imageURL) {
cell.imageView.image = image;
}
}];
return cell;
}
First of all when downloading (no matter what you use) ensure you are on correct thread. I used the easiest tool to download remote image which is using NSData and will work great as long your request don't need extra data like credentials. There is no reason for you to change it but ensure you call completion on your main thread.
Next what you are experiencing is the issue with multithreading plus cell dequeuing. In table view a same cell will be reused. When you scroll down a cell that travels up off your screen will appear at the bottom. This is to gain performance.
Now because you scroll up and down and your images load asynchronously the completion block if (succeeded) { may be called for what it seems to be an incorrect cell. What you need to do is check if the call is still valid.
So you should subclass your cell and add at least some identifier like imageURLString. You set that before you make the call to get the image and then check again on completion if the cell identifier is still the same. If it is not then your cell has been reused and the image downloaded is to be thrown away.
That also implies that you should create some sort of image caching. That way a thrown-away image is not really thrown away but is cached and if the same cell should appear the download will not occur again.

Loading images from web and displaying it in a collectionview

I am using UICollectionView to display a set of images. The images are loaded from web. I get the image URLs from an online JSON file. The images are in different sizes and i use a flowlayout to put the images together. The challenge here is that you won't know the exact size of the images until they are loaded. I use SDWebImage to download and cache the images. I use a boolean value to check which images are loaded. After each image is loaded, i tell the collectionview to reload the image at its corresponding indexpath. Now the problem is that the images do load properly but the cells are all messed up when i scroll the collectionview. Here is some code:
This is where i calculate the size of each cell:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(NHBalancedFlowLayout *)collectionViewLayout preferredSizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (didLoadImage == YES) {
return [loadedImage size];
}
else
{
return CGSizeMake(300, 140);
}
}
And here is where the images are loaded and set:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
GalleryCell *customCell = [collectionView
dequeueReusableCellWithReuseIdentifier:#"cell"
forIndexPath:indexPath];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[galleryLargeLinks objectAtIndex:indexPath.row]]];
customCell.backgroundColor = [UIColor blackColor];
[customCell.imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"placeholder"] success:^(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image)
{
loadedImage = image;
didLoadImage = YES;
[customCell.imageView setImage:image];
[collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
{
NSLog(#"fail");
[activityIndicator stopAnimating];
}];
return customCell;
}
UICollectionViewCell's are reused whenever they are scrolled off screen. And so since you are using an asynchronous block to load them, the cell may likely be assigned to another indexPath by the time it is ready to go. You can continue using the setImageWithURLRequest: if you'd like, however, you should add another check to see if the indexPath is still what you expect by the time it loads. Something like this:
[customCell setIndexPath:indexPath];
__weak GalleryCell *weakCell = cell;
__weak CollectionView *weakCollectionView = collectionView;
[customCell.imageView setImageWithURLRequest:request placeholderImage:[UIImage imageNamed:#"placeholder"] success:^(NSURLRequest *request, NSHTTPURLResponse *response,UIImage *image)
{
if([weakCell.indexpath isEqual:indexPath]){
[weakCell.imageView setImage:image];
[weakCollectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
{
[activityIndicator stopAnimating];
}];
As for the collectionView:layout:preferredSizeForItemAtIndexPath:, you need to go about that check completely differently. One option could be to make your cached images key off your datasource, so you can just check the value in the datasource array and see if it's in the cache. If it is, grab the image, otherwise return a default value. That's too much code to write out, but basically you should be checking your datasource/cache and not just two random BOOL and UIImage variables that can change at anytime.

iOS UITableViewCell imageView not working

I initialize a tableviewcell with a small image while the large image is downloading. when the large image is downloaded I notify the tableView cell imageView to update the image but nothing happens.
This is my table view cell creation method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = #"EventTableViewCellID";
EventTableViewCell *cell = [self.eventsTableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
Event *e = [_events objectAtIndex:indexPath.row];
[cell.eventTitle setText:e.eventTitle];
if (e.largeEventImage) {
[cell.eventImageView setImage:[e largeEventImage]];
} else {
[cell.eventImageView setImage:[e thumbImage]];
}
cell.event = e;
cell.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *dateString = [_formatter stringFromDate:e.eventDate];
[cell.eventDate setText:dateString];
return cell;
}
This method (in the tableView cell) is called when a image is fetched and it is supposed to update the cell image view
- (void)imagesDownloaded {
if (self.event.largeEventImage) {
[self.eventImageView setImage:_event.largeEventImage];
} else {
[self.eventImageView setImage:_event.thumbImage];
}
}
you can use AFNetworking library for that.
there is a class AFNetworking + UIImageView
this is the method for load and display the image...
[imageView setImageWithURLRequest:request
placeholderImage:#"Your thumbImage"
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
yourImageView.image = image;
}
failure:nil];
hope this helps you to done your work.

UICollectionViewCell not setting frames of labels when image is nil

What I am trying to do, I am shifting the UILabel Frames and UITextView upwards when there is no image.
It was working correctly when i do this thing locally.But now as the images are downloading from server and when i check for nil image, it is giving me wrong output.
I am trying horizontal scrolling
Here is the code what I tried
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *myCell=nil;
myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell"
forIndexPath:indexPath];
UIImageView *ImageView=(UIImageView*)[myCell viewWithTag:9];
UILabel *questionLabel=(UILabel*)[myCell viewWithTag:567];
UITextView *answerTextView=(UITextView*)[myCell viewWithTag:6];
questionLabel.text=[_questionsArray objectAtIndex:indexPath.row];
answerTextView.text=[_answerArray objectAtIndex:indexPath.row];
[ImageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http:/%#",[[_arrayOfDictionary objectAtIndex:indexPath.row] objectForKey:#"image"]]] ];
if (ImageView.image==nil) {
//Always Satisfying this condition
//Set Frame
return myCell;
}else{
return myCell;
}
}
Please provide me with solution.And also the reason Why it is satisfying if statement every-time.
(Autolayout is unchecked)
Add the AFNetworking for asynchronous solution of your image view update like
if (userBasicInfo.userImage == nil) {
__weak LGMessageBoxCell *weakCell = cell;
[cell.userImage setImageWithURLRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:userBasicInfo.imageUrl]]
placeholderImage:[UIImage imageNamed:#"facebook-no-user.png"]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
weakCell.userImage.image = image;
[weakCell setNeedsLayout];
// reload your tableView current cell here
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
}];
}

Table view scroll lagging when using SDWebImage

I am loading some images from the internet in a table view inside cellForRowAtIndexPath. Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"ArticleCell";
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
Article *article = [parser items][indexPath.row];
cell.title.text = article.title;
cell.newsDescription.text = article.description;
[cell.image setImageWithURL:[NSURL URLWithString:article.image]];
return cell;
}
My problem is that even if I use SDWebImage, when I scroll down, my app still lags. Here is some screenshots from Instruments:
It looks like even though the download of the image is performed in a background thread, the work with the image data is done in the main thread, thus it blocks your application. You could try the asynchronous image downloader provided by SDWebImage.
[SDWebImageDownloader.sharedDownloader downloadImageWithURL:imageURL
options:0
progress:^(NSUInteger receivedSize, long long expectedSize)
{
// progression tracking code
}
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
{
if (image && finished)
{
// do something with image
}
}
];
In your method it should look like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"ArticleCell";
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
Article *article = [parser items][indexPath.row];
cell.title.text = article.title;
cell.tag = indexPath.row;
cell.newsDescription.text = article.description;
[SDWebImageDownloader.sharedDownloader downloadImageWithURL:imageURL
options:0
progress:nil
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
{
if (cell.tag == indexPath.row && image && finished)
{
dispatch_async(dispatch_get_main_queue(), ^(){
cell.image = image;
});
}
}];
return cell;
}
Download the image on a separate thread, like so:
NSURLRequest *request = [NSURLRequest requestWithURL:yourURL];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( data )
{
UIImage *image = [[UIImage alloc] initWithData:data];
[cell.image setImage:image];
}
}];
This probably has less to do with network activity and more to do with your image sizes. Resizing images, especially for non-integer multipliers, is expensive. If your images are significantly larger than the view you are putting them into, you need to resize and cache them in a background thread, and reference the cached copy from your view.
To confirm if this is your issue, manually download all the images and reference the local copy. If I am correct, your UITableView will still lag the same way.
You have to load asynchronously from server so your tableView will scrolling smoothly.
Please check below answer you will be able to solve your problem.
https://stackoverflow.com/a/15331306/1713478
Check you images, check the types and size and more important: Is one or more image broken by its file format in any way? Filesize too big, irregular (to large) bounds?
Try to open and re-save suspiciously image files with an image editor, to be sure the internal file format is OK.

Resources