trafalgarlow trafalgarlow - 1 year ago 43
iOS Question

Bug with UITableViewCell ios

I'm working on an iOS project .I created an UITableView to display a list of drones . Everything works fine but I noticed that there is a bug when I click on the cell to display the details of the drone . As u can see in the images below.

When the tableView get loded

enter image description here

When clicked on cell

enter image description here

and this my code when I select a cell :

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
NSString *_storyboardName = @"Main";
UIStoryboard *_storyboard = [UIStoryboard storyboardWithName:_storyboardName bundle: nil];
DroneDetailsViewController *detailsVC = [_storyboard instantiateViewControllerWithIdentifier:@"DroneDetailsViewController"];
detailsVC.droneObj = [drones objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailsVC animated:YES];
[detailsVC.navigationController setNavigationBarHidden:NO animated:YES];

This my code for cellForRowAtIndexPath :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"drone";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
DroneObject *droneObjDisplay = nil;
droneObjDisplay = [drones objectAtIndex:indexPath.row];
NSData *data = [[NSData alloc]initWithBase64EncodedString:droneObjDisplay.modelMSide options:NSDataBase64DecodingIgnoreUnknownCharacters];
[self initCellWithComponents:cell :data :droneObjDisplay.modelName :droneObjDisplay.modelNumber];
return cell;

and this the initCelWithComponents :

- (void)initCellWithComponents :(UITableViewCell *)cell :(NSData *)dataImage :(NSString *)title :(NSString *)subTitle {

UIView *viewCell = [[UIView alloc] initWithFrame:CGRectMake(VIEW_MARGIN, VIEW_MARGIN, widthtScreen-20, VIEW_IMAGE_HEIGHT)];
viewCell.layer.borderColor = [UIColor colorWithHexString:NSLocalizedString(@"border_color", nil)].CGColor;
viewCell.backgroundColor = [UIColor whiteColor];
viewCell.layer.borderWidth = 0.5f;

image.image=[UIImage imageWithData:dataImage];
[viewCell addSubview:image];

UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(image.frame.size.width+2*VIEW_MARGIN, VIEW_MARGIN, viewCell.frame.size.width-(VIEW_IMAGE_HEIGHT-(4*VIEW_MARGIN)), 21)];
titleLabel.text = title;
titleLabel.textColor = [UIColor blackColor];
[titleLabel setFont:[UIFont systemFontOfSize:15]];
[viewCell addSubview:titleLabel];

UILabel *subTitleLabel = [[UILabel alloc]initWithFrame:CGRectMake(image.frame.size.width+2*VIEW_MARGIN, 3*VIEW_MARGIN, viewCell.frame.size.width-(VIEW_IMAGE_HEIGHT-(4*VIEW_MARGIN)), 21)];
subTitleLabel.text = subTitle;
subTitleLabel.textColor = [UIColor blackColor];
[subTitleLabel setFont:[UIFont systemFontOfSize:13]];
[viewCell addSubview:subTitleLabel];

cell.contentView.backgroundColor = [UIColor colorWithHexString:NSLocalizedString(@"gray_background", nil)];
[cell.contentView addSubview:viewCell];

any ideas how to fix that ?!

Answer Source

The TableViewCell could be designed and used by either one of the following ways,

  1. If you are using the storyboard then you can simply design the prototype cell on the TableView on storyboard itself and then giving an identifier to the cell. If you are using this way then add the component on the storyboard only and give tag to each component to access it in the code if you are not subclassing the UITableViewCell, and dequeue the cell as below,

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    UILabel *labelValue = (UILabel*) [cell viewWithTag:10];
  2. Design the TableViewCell on the storyboard as you did in 1 way and then simply create a subclass of UITableViewCell class and set that class as a Custom Class of the cell by selecting the cell on storyboard, this way you can create the outlet of each component in the cell and you do not need to access the component by the tags. Below is the code to dequeue the cell,

    CellSubClassed *cell = (CellSubClassed*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    cell.labelXYZ.text = arrayDataSource[indexPath.row][@"key"];
  3. This is the old way before storyboard was introduced, Create subclass of UITableView cell and create a xib file with the same name you give to UiTableViewCell subclass, create the outlets of component you want to access. Below is the code to dequeue cell,

    NSArray *nib;
    static NSString *strNibName = @"CustomCell";
    nib = [[NSBundle mainBundle] loadNibNamed:strNibName owner:self options:nil];
    CustomCell *cell = [nib objectAtIndex:0];
    cell.imageView.image = arrayDataSource[indexPath.row];
  4. The last way is using TableView's default cells, just create the tableView on storyboard/xib and dequeue the cell as below,

    static NSString *cellIdentifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    cell.textLabel.text = @"xyz";

The default tableView cell styles are,

  • UITableViewCellStyleDefault
  • UITableViewCellStyleSubtitle
  • UITableViewCellStyleValue1
  • UITableViewCellStyleValue2

You can read about more on Apple Developer docs here.

So in your case you are mixing the two ways of dequeuing the cell, if you want to add the component manually as you did and you don't want to design the component on the storyboard or Xib then you just create the subclass of UITableView cell and then create the component in the awakeFromNib method and dequeue the cell as explained in 3 way.

Hope it helps you.