iOS: UITableView reloadData not working
I have a UITableView with two sections: free and paid. Each section has a different kind of cell. The free cells have two labels and an image. The paid cells has two labels, an image and a button that allows the product to be bought. Once a product is bought, the BUY button on that particular cell must not be shown again. Said that, this is how the cells are initialized...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *IDNormal = @"Normal";
static NSString *IDComplex = @"Complex";
if (indexPath.section == 0) { // show free objects
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:IDNormal];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:IDNormal] autorelease];
// product description
UILabel * labelDescription = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 54.0, 225, 18)];
[labelDescription setTextAlignment:UITextAlignmentLeft];
[labelDescription setBackgroundColor:[UIColor whiteColor ]];
[labelDescription setClipsToBounds:YES];
[labelDescription setFont:[UIFont systemFontOfSize:14.0]];
[labelDescription setTextColor:[UIColor blackColor]];
[labelDescription setAlpha:0.6];
[labelDescription setTag: 860];
[cell addSubview:labelDescription];
[labelDescription release];
// this will show the word FREE on free objects (cells)
UILabel * labelFREE = [[UILabel alloc] initWithFrame:CGRectMake(235.0, 54.0, 80, 18)];
[labelFREE setTextAlignment:UITextAlignmentCenter];
[labelFREE setBackgroundColor:[UIColor greenColor ]];
[labelFREE setClipsToBounds:YES];
[labelFREE setFont:[UIFont boldSystemFontOfSize:14.0]];
[labelFREE setTextColor:[UIColor blackColor]];
[labelFREE setAlpha:0.75];
[labelFREE setText:NSLocalizedString(@"freeKey", @"")];
[labelFREE setTag: 861];
[cell addSubview:labelFREE];
[labelFREE release];
}
cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat: @"free%d", indexPath.row] ofType:@"jpg"]];
NSString * prefixLabel = [NSString stringWithFormat: @"gratis%d", indexPath.row];
UILabel *labelDescription2 = (UILabel*)[cell viewWithTag:860];
[labelDescription2 setText:@"FREE"];
return cell;
} else { // show paid objects
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:IDComplex];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:IDComplex] autorelease];
UILabel * labelDescription = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 54.0, 225, 18)];
[labelDescription setTextAlignment:UITextAlignmentLeft];
[labelDescription setBackgroundColor:[UIColor whiteColor ]];
[labelDescription setClipsToBounds:YES];
[labelDescription setFont:[UIFont systemFontOfSize:14.0]];
[labelDescription setTextColor:[UIColor blackColor]];
[labelDescription setAlpha:0.6];
[labelDescription setTag: 1];
[cell addSubview:labelDescription];
[labelDescription release];
}
int numberPaidObject = indexPath.row + 500;
cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat: @"table-pg%d", numberPaidObject] ofType:@"jpg"]];
NSString * nomeDoProduto = [NSString stringWithFormat: @"paid%d", numberPaidObject];
if ( NotSoldProduct ) {
NSString * prefixoEtiqueta = [NSString stringWithFormat: @"paid%d", numberPaidObject];
UILabel *labelDescription2 = (UILabel*)[cell viewWithTag:1];
[labelDescription2 setText:[description objectAtIndex: numberPaidObject ];
}
return cell;
}
}
as I have to identify which BUY button was clicked and I am using dequeueReusableCellWithIdentifier, so I have to use the following method...
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
int numeroOfPaidObject = indexPath.row + 500;
if ((indexPath.section == 1) && ObjectForSale) {
// if paid objects and object was not bought yet
// in theory this section will not be executed if the object was already bought and paid
// so, I am skipping the BUY button creation and, in 开发者_开发问答theory the cell will not have a BUY
// button… the problem is that it does...
UIButton * buyButton = [[UIButton alloc] initWithFrame:CGRectMake( 235, 45, 80, 30)];
buyButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
buyButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[buyButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
buyButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
buyButton.backgroundColor = [UIColor clearColor];
[buyButton addTarget:self action:@selector(buyNow:) forControlEvents:UIControlEventTouchDown];
[buyButton setTitle:NSLocalizedString(@"buyKey", @"") forState:UIControlStateNormal];
UIImage *newImage = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
pathForResource: @"whiteButton" ofType:@"png"]]
stretchableImageWithLeftCapWidth:12.0f topCapHeight:0.0f];
[buyButton setBackgroundImage:newImage forState:UIControlStateNormal];
[buyButton setTag: numeroOfPaidObject];
[cell addSubview:buyButton];
[buyButton release];
}
}
The problem with this code is: when I reload table's data the BUY button continues to show up on all cells, including those that was already bought by the user.
Any ideas?
thanks for any help.
You can step through it with the debugger, but here is my guess:
Because table cells are being reused, eventually all of the already purchased items end up in table cells that were previously occupied by an unpurchased item and therefore have had a buy button added to them.
If this is the case you need to add an else
clause in your second section of code that deletes the button from the cell if the product has already been purchased.
Another problem is that your code is adding a new button every time a cell is displayed, so many/most of your cells probably have several buttons in them.
You will want to refactor your code so that the button is added once, in tableView:cellForRowAtIndexPath:
, and only for newly-created cells.
There are two ways to do that:
Split the "Complex" cell type into two types: purchased and unpurchased, and create/dequeue them separately. Add the button only to to the unpurchased cell type.
Add the buttons to all of the cells in the "paid" section, and hide it when the item has been purchased.
In either case you'll need a way to grab a pointer to the button. The preferred way to do this is with the tag
property, making it a one liner:
UIButton * button = [cell viewForTag:42];
...
You can also iterate through the subviews of the cell looking for UIButton objects:
UIButton *button = nil;
foreach (UIView *view in cell.subviews) {
if ([view isKindOfClass:[UIButton class]])
button = (UIButton *)view;
}
I would suggest using a constant tag to identify the button, and then rewrite your buyNow:
method as follows:
-(IBAction)buyNow:(id)sender {
UITableViewCell *cell = (UITableViewCell *)((UIView *)sender).superview;
int itemID = [tableView indexPathForCell:cell].row + 500;
...
}
Perhaps I am thinking too simply here but a table view will function just fine with only the delegates set, but will fail to respond to reloadData if you have not made the connection in IB, did you check that?
精彩评论