UITableViewCell Image not updating - objective-c

I can update the detailTextLabel.text and the UITableViewCell shows the changes at runtime, but if I try to update the imageView.image it does not change the visible image. Any idea as to why? I have tried calling a refresh on the UITableViewCell specifically but to no avail.
-(void)getImageForURL:(NSURL*)url row:(UITableViewCell*)cell {
UIImage*image;
image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url];
cell.imageView.image = image; // Does not work..
cell.detailTextLabel.text = #"test"; // Works
}

Try calling [cell setNeedsLayout] after setting the image, if it's the first image you're setting for the cell.

Make sure the cell style is UITableViewCellStyleDefault, because other cell types may always return nil imageView, instead of creating one on demand.

Check whether the image is nil or not. If its nil then the Image is not fetched from the URL correctly.

I too was having problems with adding the image to my imageView that was constrained in a tableview cell and was not updating with cell.setNeedsLayout(). Calling update methods on the tableview after the image was added did the trick for me:
cell.setNeedsLayout()
if #available(iOS 11.0, *) {
tableView.performBatchUpdates(nil, completion: nil)
}
else {
tableView.beginUpdates()
tableView.endUpdates()
}

Related

SetNeedsDisplay in table view

My problem is that not all cell are correct initialized with the correct UIView as an rendered image.( see code below) On a iphone 4 it always the same cel on a iphone with retina display is also an other cell. In this set-up setNeedsDisplay won't function.
If i use the same structure in an IBoutlet it's working.
!
I need to use in some cells the image-files .png and at some other cells the defined drawing method, which uses the drawrect or better i should use the setNeedsDisplay method.....
What is going wrong!!!
my code
tableview... cell
static NSString *CellIdentifier = #"TypeCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
CellTypes *cellType = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = cellType.title;
cell.detailTextLabel.text = cellType.detail;
if ( [cellType.type rangeOfString:#"TL"].location != NSNotFound) {
cell.imageView.image = [UIImage imageNamed:[cellType.type stringByAppendingString:#"Thumb"]];
cell.indentationWidth = 10;
}
else {
static CGFloat scale = 0.0; // old API , screen values
UIScreen *screen = [UIScreen mainScreen];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.0) {
scale = [screen scale];
}
if (scale>0.0) {
UIGraphicsBeginImageContextWithOptions(cell.imageView.bounds.size, NO, scale);
}
else {
UIGraphicsBeginImageContext(cell.imageView.bounds.size);
}
CGRect imageRect = CGRectMake(0, 0, 84, 84 ); // cell.imageView.bounds;
FittingImageView *fittingImage = [[FittingImageView alloc] initWithFrame:imageRect];
fittingImage.thumb = YES;
fittingImage.title = offSetType.title;
[fittingImage drawRect:imageRect]; // this works but skips one imageRect
// [fittingImage setNeedsDisplay]; //this won't work.
[cell.layer renderInContext:UIGraphicsGetCurrentContext()];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return cell;
You can never call drawRect: yourself. It is called by Cocoa, and only Cocoa can setup the context. It's unclear what you're trying to do here. I don't know what a FittingImageView is. You're creating it and then throwing it away in any case.
You then try to render the cell itself into an image, and the put that image into the cell's imageview. That doesn't make sense.
You may misunderstand how tableview cells are created, reused and drawn. You should re-read "Creating and Configuring a Table View."
The primary things to remember:
In this routine, your job is to either create a new cell, or reconfigure a reusable cell (if dequeueReusableCellWithIdentifier: returns you something).
This routine is not for drawing a cell. That will happen much later, and it is the cell's job to draw itself. You're just configuring the cell. Putting everything in it that it needs to draw later.
You typically do not want to compute expensive things in this routine. Compute those elsewhere and cache them. This routine should configure a cell, slap data into it, and return. If you try to create new images in this routine, your table view is going to stutter.
You shouldn't mess with the cell's layer in the middle of this routine. If you need something that complex, you should be creating a custom cell with its own drawRect:.

UITableViewAccessoryType Randomly Not Showing

For each cell in the TableView I basically have a Boolean variable that stores if the data is being loaded for that cell. So tapping on a cell will cause the accessory type to change to a UIActivityIndicator. The TableView loads fine, but when I pop back to the TableView one or two of the cells randomly do not have the default DisclosureIndicator... it has nothing
The code I am using is inside cellForRowAtIndexPath
NSLog([entry isLoading] ? #"Yes" : #"No");
if ([entry isLoading]) {
UIActivityIndicatorView *activityView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[activityView startAnimating];
[cell setAccessoryView:activityView];
}
else{
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
I have stepped through the code and the cells that do not show the DisclosureIndicator are still running the code that is setting it to a AccessoryDisclosureIndicator... I'm not sure what's going on since the cells missing the indicatory is triggering the else statement causing the setAccessoryType
Thanks!
Try this,
if ([entry isLoading]) {
UIActivityIndicatorView *activityView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[activityView startAnimating];
[cell setAccessoryView:activityView];
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
else{
[cell setAccessoryView:nil];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
As per documentation,
accessoryView
If the value of this property is not nil, the UITableViewCell class
uses the given view for the accessory view in the table view’s normal
(default) state; it ignores the value of the accessoryType property.
The provided accessory view can be a framework-provided control or
label or a custom view. The accessory view appears in the right side
of the cell.
So you need to set accessoryView to nil show the accessoryType or else it will ignore it.

Check whether +[UIImage imageNamed:] found an image

I have an long if statement to decide what image to show in a UIImageView. They are all .png files, and I use the code:
if (whatever) {
image = [UIImage imageNamed: #"imageName.png"];
}
Does anyone know of a way to check to see if the program can find the image? So that if the image does not exist in the program, it can display an error image or something?
+[UIImage imageNamed:]
will return nil if it couldn't find a corresponding image file. So just check for that:
UIImage *image = [UIImage imageNamed:#"foo.png"];
if (image == nil)
{
[self displayErrorMessage];
}
The shortest snippet would be
image = [UIImage imageNamed:#"imageName"] ? : [UIImage imageNamed:#"fallback_image"]
but do you really want such code?
Make another check:
if (whatever) {
image = [UIImage imageNamed: #"imageName.png"];
if(image == nil) {
image = [UIImage imageNamed: #"fallback_image"];
}
}
it still can be shorted, like
if(! (image = [UIImage imageNamed: #"imageName.png"]) ) {
...
}
but you're toying with readability here.
First, I'd suggest using a dictionary instead of a long if. You can key each image name by whatever. If whatever isn't currently an object, make an enum that will encapsulate that information and use NSNumbers to box the values of the enum.
Then, you can check for nil when you try to retrieve the image. imageNamed: uses nil to indicate failure, so:
if( !image ){
// No image found
}

Resize downloaded image from URL using SDWebImage from YouTube JSON EDITED

I'm downloading thumbnail images from youtube JSON web service using SDWebImage, in order to set them in a table view cell. The problem is that the download image is 120x90, too big for my needs , as I want to fit it in a UIImageView of 75x75. While the images are cached in the placeholder, they look correct, but once cache is finished, they look in the 120x90 ratio size. I tried setContentMode:UIViewContentModeScaleToFill, but it doesn't work, so I don't know how to solve this issue.
NSString *path= [thumbnail valueForKey:#"sqDefault"];
[cell.imageView setImageWithURL:[NSURL URLWithString:path] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
[cell.imageView setContentMode:UIViewContentModeScaleToFill];
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:5.0];
Many thanks
EDITED:
I have set content mode in the custom cell extended class:
newsCell.m
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self.Image setContentMode:UIViewContentModeScaleToFill];
}
return self;
}
And here is the cell creation code:
multimedia.m
newsCell *cell = [self.tableView
dequeueReusableCellWithIdentifier:#"news"];
if (cell == nil) {
cell = [[newsCell alloc] initWithStyle:UITableViewCellSelectionStyleNone reuseIdentifier:#"news"];
}
The issue is that if (cell == nil) is never called because first statement is creating cell, so initWithStyle is not called and content mode is not set, but if I delete first statement, cell is not created. I don't know how to manage it.
Thanks
Try these two options and see which better fits your needs:
UIViewContentModeScaleAspectFit
UIViewContentModeAspectFill
If these don't work, I am guessing it is because the UITableViewCell is setting the contentMode on the UIImageView -- in this case you should create a subclass of UITableViewCell that contains a UIImageView with the proper contentMode set. Then you can use your custom UITableViewCell subclass in your UITableView.
Set custom size of your table image view in its custom cell class
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(5,5,40,32.5);
float limgW = self.imageView.image.size.width;
if(limgW > 0) {
self.textLabel.frame = CGRectMake(55,self.textLabel.frame.origin.y,self.textLabel.frame.size.width,self.textLabel.frame.size.height);
self.detailTextLabel.frame = CGRectMake(55,self.detailTextLabel.frame.origin.y,self.detailTextLabel.frame.size.width,self.detailTextLabel.frame.size.height);
}
}
For more details please refer this link

Complex For & If loop confusion, returning and accessing classes. Objective-C

I have a view which has a number of subviews. I need to find a particular UIImageView with a particular UIImage.
Here is the code I'm using to loop through:
BOOL fileExistsAtLocation;
for (id subview in drawGallery.subviews){
if ([[subview class] isSubclassOfClass: [UIImageView class]]){
// I need to detect the subview's image property to see if it matches.
}
}
I've tried
if(subview.image == [UIImage imageNamed:image]){
}
But I'm getting told that image isn't part of the structure, which is understandable as all the subviews are essentially of UIView type. How do I target only the UIImageViews and then check their image property?
Regarding the 'tag' answer, the code I tried was:
BOOL fileIsAtLocation;
for (id subview in drawGallery.subviews){
if ([subview isKindOfClass:[UIImageView class]]){
if ((UIView *)subview.tag){
NSLog(#"FOUND");
}
}
}
[UIImage imageNamed:image] will return a new instance of that image so it will NEVER be equal. I'd suggest tagging all of your subviews. So when you create the image views, assign a unique tag (this could just be an auto incrementing number). Then you can detect of interest based on the tag.
BOOL fileExistsAtLocation;
for (id subview in drawGallery.subviews){
if ([subView isKindOfClass:[UIImageView class]){
// I need to detect the subview's image property to see if it matches.
if([(UIView *)subView tag] == uniqueIDAssignedToImage) {
// You have found your view
}
}
}
Also use isKindOfClass to check the class type.
Hope this helps.
Did you try to use type conversion?
if(((UIImageView *)subview).image == [UIImage imageNamed:image]){
}
UPDATE:
You can also try to change iteration logic:
for (UIView *subview in drawGallery.subviews) {
If you have to find a single view with tag, try
UIImageView *imageViewISearchFor = [drawGallery viewWithTag:uniqueIDAssignedToImage];