xcode ios: in cell image overlaps on the label - objective-c

I am displaying an image on my cell in the table. I have the code within
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
While I am using storyboard, so I displayed the image in the cell with
cell.imageView.image = [UIImage imageNamed:_lotImagesArray[row]];
However, when I tried to load the image from a webserver, The image sits on top of the label in the cell (blocking the label text)
The code I used to display the image from webserver is this:
NSString *strURL = [NSString stringWithFormat:#"http://www.domainhere.com/images/%#", lotPhoto[row]];
NSURL *url = [[NSURL alloc] initWithString:strURL ];
cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
Can someone please advice where did I go wrong?

A couple of likely possibilities:
First, you might want to double-check to make sure that you have
cell.imageView.clipsToBounds = YES;
If you don't, when it sizes the image to fit in the UIImageView, the image can bleed over the bounds of the image view. I notice this problem, especially, when I'm doing this image loading in a background queue.
Second, if you're setting the imageView property of the UITableViewCell in the background (like the simplified sample code below), you should know that it's important to properly initialize the image with a blank image before you kick off the background image loading process. So, an example of very common code when loading a cell from a web based source is something like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.textLabel.text = ... // you configure your cell however you want
// make sure you do this next line to configure the image view
cell.imageView.image = [UIImage imageNamed:#"blankthumbnail.png"];
// now let's go to the web to get the image
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
UIImage *image = ... // do the time consuming process to download the image
// if we successfully got an image, remember, ALWAYS update the UI in the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// let's make sure the cell is still visible (i.e. hasn't scrolled off the screen)
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell)
{
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.clipsToBounds = YES;
}
});
});
return cell;
}
Clearly, if you do something like that, you'll want to make sure that the [UIImage imageNamed:#"blankthumbnail.png"]; is not returning nil (i.e. make sure your app is successfully finding it in the bundle). Common problems might include failure to have a blank image at all, a mistake in the name, failure to include the image in your Target settings, under the "Build Phases" tab, under "Copy Bundle Resources".
Third, you need to make sure that when you're using subclassed UITableViewCell entries, that you don't use the standard UITableViewCell property names of imageView, textLabel, etc. Make sure to use your own, unique names. If you use imageView, the system gets confused between your new IBOutlet and the default imageView property of the UITableViewCell.

Related

In UITableViewCell, UIImageView content repeats after some cells using AFNetworking

The content is distinct on all the cells on the first page but as we scroll down, only the UIImageView is repeated though the UILabels are distinct.
I am using [UIImageView setImageWithURL:(NSURL *)url] from AFNetworking which was included in the RestKit. Heres the implementation
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RClubTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"RClubTableViewCell"];
RClubObject * club = _clubs[indexPath.row];
[cell.clubImageView setImageWithURL:[NSURL URLWithString:club.clubImageURL]];
cell.nameLabel.text = club.clubName;
return cell;
}
Seems like iOS is somehow using the previously created cells. Would like to have completely fresh cells while scrolling.
You need to call setImageWithURL:placeholderImage: with a non-nil placeholder image to have the old image removed from the image view.
I guess you missed reallocation in your cellForRowAtIndexPath:
Your code should be something like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RClubTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"RClubTableViewCell"];
if(cell == nil)
{
cell = [[RClubTableViewCell alloc] init];
}
RClubObject * club = _clubs[indexPath.row];
[cell.clubImageView setImageWithURL:[NSURL URLWithString:club.clubImageURL]];
cell.nameLabel.text = club.clubName;
return cell;
}
Update :
Okay. I just had the same issue. Here what my search over google tells me : Since you are downloading the image in async and also scrolling, it gets downloaded and attached to other cells which are currently visible
Solution:
add tag to each imageView using indexpath.row
Use function setImageWithURL: placeholderImage:success:
In success block reload the cell using the tag value.
Though I haven't tested this I feel this should work. PS : Let me know if this works I also would have to do the same then :)
Yes, iOS is reusing the previously created cells. That is what this line of code does, so that the app does not have to spend the time creating a new cell from scratch:
RClubTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"RClubTableViewCell"];
Clear the image from the recycled cell before adding the new image for this cell:
cell.clubImageView.image = nil;
[cell.clubImageView setImageWithURL:[NSURL URLWithString:club.clubImageURL]];
cell.nameLabel.text = club.clubName;
return cell;
Alternatively, you could create a new cell from scratch instead of dequeuing one.

UICollectionView, Images inside a cell does not load until the cell is scrolled off screen

Using Xcode 6 beta 6, I have used a standard View Controller and placed a Collection view into it. Following this, I have added a prototype cell from which an array on the CollectionViewController.m file provides the images.
While the images do appear, they do not load until after that cell has been scrolled off the screen and then back on. This is stopping any images from loading when the app opens until the user scrolls down.
The images are stored locally in the file, not a Database.
Despite the lack of images, I have linked the cells to another view controller, and even though no image is displayed, the segue still operates.
Thanks for any help in advance.
I guess you are setting the UIImage on the cell image view out of the main thread. Wrap the setter code into a following snippet:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
cell.imageView.image = {UIImage object you've got};
}];
Optionally you could also try different, single-line replacement approach, if possible:
[cell.imageView performSelectorOnMainThread:#selector(setImage:) withObject:{UIImage object} waitUntilDone:NO];
I can't find what kind of cell you mean in fact; in every case, apply the same on a particular target image view, no matter if it's a part of your cell as a property or not.
you should use willDisplayCell method to assign image.
first initial image then create cell.
here is the code :
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
return cell;}
-(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];
imageView.image = images[indexPath.row];}
And don't forget to reload collection view after your data is ready to be loaded:
[_myCollection reloadData];

Storyboard - static cell in Detail view - managing buttons dynamically

I've recently found a way to solve displaying a button when data exists and not when no data is in a cell. Specifically using Storyboards in a detail view (static cell). This button is a necessity on the Storyboard due to some seque wiring I've hooked up.
I placed a custom button with no background image on it, and set a tag value of the tableviewcell to 1.
Then in my implementation file I've overridden the cellForRowAtIndexPath.
My question is, while this works fine, is it performance intensive? I have only 5 cells in this MOC. Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
// need to capture the section and the cell to modify....
if (cell.tag == 1){
if (self.map){
self.mapButton.enabled = YES;
self.mapLabel.text = #"Click Map for Pic Location...";
UIImage *buttonImage = [UIImage imageNamed:#"MyMap.png"];
[self.mapButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
} else{
self.mapLabel.text = #"No Location found for Pic";
self.mapButton.enabled = NO;
}
}
return cell;
}

Updating subviews in cells on a UITableView

I'm developing an application in iPad 6.0 using Storyboards.
Let me first explain my goal. I'm trying to achieve a Master-Detail (SplitViewController-like) View Controller using 2 UITableViewControllers.
The first UITableView("Master"), let's call this HeaderTableView, as the name implies, lists down the Headers for the...
...Second UITableView("Detail"), let's call this the EncodingTableView, which contains a programmatically changing CustomTableViewCell (subviews contained within each cell may be a UITextField, UIButton or UISwitch).
See EncodingTableView.m
- (void)updateEncodingFields:(NSArray *)uiViewList
{
// Add logic for determining the kind of UIView to display in self.tableView
// Finally, notify that a change in data has been made (not working)
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *encodingFieldsTableId = #"encodingFieldsTableId";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:encodingFieldsTableId];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:encodingFieldsTableId];
}
// Change text in textView property of CustomTableViewCell
cell.encodingFieldTitle.text = uiViewList.title;
// added methods for determining what are to be added to [cell.contentView addSubView:]
// data used here is from the array in updateEncodingFields:
}
My HeaderTableView.m, contains the didSelectRowAtIndexPath to update the EncodingTableView
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (![selectedIndexPath isEqual:indexPath]) {
selectedIndexPath = indexPath;
[self updateDataFieldTableViewForIndexPath:indexPath];
}
}
- (void)updateDataFieldTableViewForIndexPath:(NSIndexPath *)indexPath {
[self.encodingTableView updateEncodingFields:self.uiViewList];
}
Question
- Data is all ok but why doesn't EncodingTableView "redraw"ing the fields? My
suspicion is that reusing cells has something to do with this but I just can't figure out why.
Screenshots on the result:
Initial Selection in HeaderTableView
Second Selection in HeaderTableView
What I've tried :
I kept seeing suggestions such as [UITableView setNeedsDisplay],
[UITableView reloadData] and [UITableView setNeedsLayout] but none of
them worked.
Removing the reuse of tableViewCells works fine but this causes parts of my
CustomTableView.encodingFieldTitle to disappear. Not to mention that this might cause performance issues if I were to drop reusing cells.
Restrictions:
I know that a good idea is to use a SplitViewController but this is just a subpart of my app (hence not the RootViewController).
Finally, thanks for reading such a long post. ;)
It looks like you are most likely adding subviews inside tableView:cellForRowAtIndexPath:.
The issue is that if you use cell reuse then are not always starting from a blank slate inside tableView:cellForRowAtIndexPath: instead you can possibly be given a cell back that has already been configured once. This is what you are seeing, a cell that has previously had labels added to it is handed back to you and then you add some more labels over the top.
There are a few way to deal with this:
(My preferred option) Create a subview of UITableViewCell with these extra sub views available as properties.
Ensure the cell setup is only done once
A great place to do this is when you actually create a cell when one does not already exist e.g. inside the if (cell) check
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:encodingFieldsTableId];
// add subview's here and give them some way to be referenced later
// one way of doing it is with the tag property (YUK)
UILabel *subView = [[UILabel alloc] initWithframe:someFrame];
subView.tag = 1;
[cell.contentView addSubview:subView];
}
UILabel *label = (id)[cell.contentView viewWithTag:1];
label.text = #"some value";
One problem i can see in your code is that the cell identifiers used are different in tableView cellForRowAtIndxPath function.
While dequeueing you are using this identifier - > "encodingFieldsTableId"
&
while creating a cell you are using this identifier - > "dataFieldUiGroupTableId".
Ideally these two identifiers should be same !!!
Try adding,
cell.encodingFieldTitle.text = nil;
Before if(cell == nil)
So that whenever your cellForRowAtIndexPath method is called, the string already present in the cell you are going to reuse will get deleted and the new text in uiViewList.title will be displayed.

UITableViewCell strange behavior when on select changing an image inside

I have a problem while using a custom extended UITableViewCell with a nib file for a UITableView in my iPad application.
This cell have a behavior when selecting it to change a checkmark image from selected to unselected depended if it was selected, I use custom images for this and not the default check cell Apple have.
So everything in my functionality seems to be correct. I post some code.
I use the registerNib method to load the nib cell.
[tableView registerNib: [UINib nibWithNibName: #"ANibTableViewCell" bundle: nil] forCellReuseIdentifier: Identifier];
The nib cell is extended with a class file and managed through it, connecting outlets append model values etc.
In cellForRowAtIndexPath:
- (UITableViewCell*) tableView: (UITableView*) tableView cellForRowAtIndexpath: (NSIndexPath*) indexPath
{
ExtendedtableViewCell* cell;
AModel* model;
cell = [tableView dequeueReusableCellWithIdentifier: Identifier];
model = [modelForDisplay objectAtIndex: indexPath.row];
cell.model = model;
// Some operations setting the check mark if it needed etc.
// Checkmark is a UIImageView in the nib cell that just changes image on selection
// Some other operations happening notified by the model if selected or unselected
return(cell);
}
My problem is so strange now, lets say that you visually have 6 cells and you select the first 3, all fine, but if you scroll down to see the next cells, lets say you scroll 6 rows down you notice that always per 6 cells the 3 first looks selected, but the extended cell class instance which I keep if its selected or not is not in selected state. What visual effect is that?
Try this,
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *Identifier = [NSString stringWithFormat:#"cell%d.%d",indexPath.section,indexPath.row];
ExtendedtableViewCell* cell;
AModel* model;
cell = [tableView dequeueReusableCellWithIdentifier: Identifier];
model = [modelForDisplay objectAtIndex: indexPath.row];
cell.model = model;
// Some operations setting the check mark if it needed etc.
// Checkmark is a UIImageView in the nib cell that just changes image on selection
// Some other operations happening notified by the model if selected or unselected
return(cell);
}
hope it will helps you.....