I want to show an image on the right side in a UITableViewCell.
I'm using this code, to do it:
CGRect imageRect = {80,0,225,44};
UIImageView *uiv = [[UIImageView alloc] initWithFrame:imageRect];
[uiv setImage:[UIImage imageNamed:[NSString stringWithFormat:#"star%#.png", [[self reataurant] valueForKey:#"stars"]]]];
[uiv setClipsToBounds:YES];
[cell addSubview:uiv];
My problem is, that the image is shown in other cells, when i'm scrolling the tableview.
What am i making wrong?
What is probably happening is that you are re-using cells that already have an image when you do not wish to. Check
a) when you re-use a cell, if it has the star image then remove it.
b) before you return the cell add the star at that point (with whatever test you use to determine if the star should appear).
Those UITableViewCells are reused. Look in your cellForRowAtIndexPath for
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
If you only want one or a certain set of cells to have this particular layout, you can pass a different cellIdentifier for these cells.
You can easily add an image view as the accessory view to a table cell for the same effect.
Here is the sample code for your understanding:
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"fileName"]];
cell.accessoryView = imageView;
[imageView release];
And make sure you are reusing cell space of a table view in cellForRowAtIndexPath method by using a cell identifier so that overwritten problem can be eliminated ;)
NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
Hope that should eliminate your problem of images getting displayed on one another,thanks :)
Related
Trying to add an UIImage into default UITableViewCell. The image was appeared, but part of separator line (under the image) became disappeared. How can I fix that?
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = #"text";
cell.imageView.image = [UIImage imageNamed:#"map.png"];
That's how it looks like now - screenshot
I suggest you add this line of code after you instantiate de UITableView:
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
If this doesn't work, I suggest that you execute the app on a real device. I have had a similar problem some days ago, and the problem was with the iOS simulator...
I hope this helps!
I'm struggling with this basic thing for more than a day and it drives me crazy! Funny thing is, I have very similar thing on other screen and it works just fine! I have done this a thousand times, but never experienced something so odd. Maybe is this behavior in iOS 8 only?
On my very simple Prototype cell I have two labels with tags 102 and 103. But when I want to set text to them, they are always nil.
I have double checked that identifier is correct and that tag is the same as in Storyboard.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * identifier = #"secondReusableIdentifier";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
for (UIView *subview in [cell subviews]) {
NSLog(#"subview: %lu", subview.tag); // prints 0
}
UILabel * label1 = (UILabel *)[cell viewWithTag:102]; // returns nil
UILabel * label2 = (UILabel *)[cell viewWithTag:103]; // returns nil
if (self.items.count) {
MyObject *obj = [self.items objectAtIndex:indexPath.row];
label1.text = obj.someProperty;
fuelPrice2.text = obj.someOtherProperty;
}
}
return cell;
Any suggestions would be appreciated.
In your code you are creating a new cell, that it's not the same than you have in Storyboard.
Change this: This is the old way, or the way you use when the cell is by code or nib, and you don't use storyboard. This code means.
NSString * identifier = #"secondReusableIdentifier";
// If I have available a cell with this identifier: secondReusableIdentifier, let's go to use it.
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
// If not, we create a new cell with this identifier. This methods is previous to storyboard, and this methods create a new cell, but does´t look in Storyboard if this identifier exist, or something like that.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
To this, in other hand when Apple launched storyboard the framework grow with this methods, that work in this way: If there is a cell free use it, if not it look in Storyboard for a cell with this identifier and create a new cell with this info. (You can use this methods also by code and with nib file, but you must register the class before...).
// Be sure than: "secondReusableIdentifier", it's its identifier in storyboard
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"secondReusableIdentifier" forIndexPath:indexPath];
Replacing this:
NSString * identifier = #"secondReusableIdentifier";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
BY
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"secondReusableIdentifier" forIndexPath:indexPath];
for creating a cell will solve your problem because, it always returns a cell. It either re uses existing cells or creates a new one and returns if there are no cells.
The most important difference is that the forIndexPath: version crashes if you didn't register a class or nib for the identifier. The older (non-forIndexPath:) version returns nil in that case.
You must register a class or nib for using this. But if you create your table view and your cell prototypes in a storyboard, the storyboard loader takes care of registering the cell prototypes that you defined in the storyboard.
Hope this helps.. :)
If
for (UIView *subview in [cell subviews]) {
NSLog(#"subview: %lu", subview.tag); // prints 0
}
prints 0, why do you do this??
UILabel * label1 = (UILabel *)[cell viewWithTag:102];
UILabel * label2 = (UILabel *)[cell viewWithTag:103];
So, if you created a custom cell with IB, you have to create a custom class and use it instead of a simple UITableViewCell
i am able to fetch images asynchronously on to uitableview.i am fetching these images are from a url.on scrolling up uitableview these images disappear and they take time to load again and sometimes they dont load at all.i dont want to use any 3rd party libraries.i dont want to go with synchronous approach.please suggest any correct approach to improve performance.thanks for help in advance.my code is below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier=#"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"identifier"];
}
UIImageView *imgVw=[[UIImageView alloc]initWithFrame:CGRectMake(250, 10, 40, 30)];
[cell.contentView addSubview:imgVw];
Attributes *att = [listOfObjects objectAtIndex:indexPath.row];
strImgUrl=#"http:image url";
strImgName=att.classifiedImg;
if (strImgName == nil) {
UIImage *myImg=[UIImage imageNamed:#"user_circle.png"];
imgVw.image=myImg;
}
else{
strImg=[strImgUrl stringByAppendingString:strImgName];
}
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData *data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:strImg]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *img=[UIImage imageWithData: data];
imgVw.image=img;
});
});
return cell;
}
UITableViews are designed to reuse cells. When you scroll up for example the first cell might get reused to show the 5th cell since the 1st one is now off screen. When you scroll back up cellForRowAtIndexPath is called again, and you are async downloading the same image again. If you want to have it load instantly you will need to cache the images after downloading them the first time so the next time that image is needed you can directly pull it from the cache.
Many third party libraries do this (AFNetworking), but if you don't want to use them, you will have to cache the images manually.
It seems like your reuse code contains bug, which causes everytime to create new cells. The following code uses reuseIdentifier as #"identifier"
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"identifier"];
}
Change it to:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
EDIT:
On reusing tableView cells, you dont need to create and add subviews to cell each time. Instead, just create the subview when creating cell and then if cell is reusing, just get the subview using tag and update your content from datasource.
Your code can be modified like below:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
UIImageView *imgVw=[[UIImageView alloc]initWithFrame:CGRectMake(250, 10, 40, 30)];
imgVw.tag = indexPath.row;
[cell.contentView addSubview:imgVw];
}
UIImageView imgVw = (UIImageView*)[cell.contentView viewWithTag:indexPath.row];
//Rest is same as you posted.
Hope this will fix the issue.
I've a grouped UITableView and I've set the background of one of its cells to be a gradient image, this way:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
cell.textLabel.text = NSLocalizedString(#"Add item", #"");
cell.textLabel.backgroundColor = [UIColor clearColor];
UIImage* image1 =[[UIImage imageNamed:#"gradient_normal"] stretchableImageWithLeftCapWidth:5.0 topCapHeight:0.0];
UIImage* image2 =[[UIImage imageNamed:#"gradient_selected"] stretchableImageWithLeftCapWidth:5.0 topCapHeight:0.0];
cell.backgroundView = [[UIImageView alloc] initWithImage:image1];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:image2];
}
return cell;
}
Background of the cell is correctly displayed, but it has not rounded corners anymore, as the rest of the cells at top and bottom of the table and with default background have... I tried setting the cornerRadius property of the table view, but it didn't work. And I was not able to set the cornerRadius for the particular cell.
The only post I found dealing with this same problem had not been actually answered (grouped tableViewCell - no rounded corner after setting the background of a grouped table cell), could somebody help me with this issue?
Thanks in advance
If you are allowed/able to use outside libraries, checkout PrettyKit, makes it quite easy.
If you have to do it on your own, the best way to go about this is to subclass UITableViewCell and create your own custom cells. Here is a good tutorial
I have a table in my iOS app with three table cells, and they each have a custom Accessory button. One of the cells needs to be taller than the others; it is 60px instead of 45px. In this case, the accessory button gets scooted over to the left, whereas if they were all the same height, the accessory button would line up.
The accessory buttons are created by the same code, so they should be identical. The issue seems to be related to the UITableViewCell itself.
It ends up looking like this. I failed to include the upper border in the screen grab, but the upper cell is the taller one. Does anyone know how I could fix this?
Here's an example of how the cells are created. These differ only in name; the height is specified by tableView: heightForRowAtIndexPath:
cell = [[UITableViewCell alloc] init];
label = [[UILabel alloc] initWithFrame:[cell frame]];
[label setText:#"Favorites"];
[cell.contentView addSubview:label];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
button = [UIButton buttonWithType:UIButtonTypeCustom];
image = [UIImage imageNamed:#"GT.png"];
[button setBackgroundImage:image forState:UIControlStateNormal];
button.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
[cell setAccessoryView:button];
You are setting the accessory view and the accessory type. Do one or the other. I would get rid of setAccessoryView:button.
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
[cell setAccessoryView:button];
Also, why are you doing this:
cell = [[UITableViewCell alloc] init];
You should be creating your cell in cellForRowAtIndexPath you should having something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = nil;
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"Some Text";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}