iOS - Custom AccessoryView not showing in UITableViewCell

2k views Asked by At

I have tried to show a custom view with an accept button and decline button (as subviews) in a table view cell. I have the following code implemented:

tableView: cellForRowAtIndexPath: method

...
if ([status isEqualToString:@"pending"] || [status isEqualToString:@"declined"]){
    cell.accessoryView = [self setAccessoryViewForCell:cell];
} else {
    cell.accessoryType = UITableViewCellAccessoryNone;
}
...

- (UIView *)setAccessoryViewForCell:(UITableViewCell *)cell
{
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(192, 0, 128, 44)];
    UIButton *acceptButton = [[UIButton alloc] initWithFrame:CGRectMake(2, 5, 60, 34)];
    UIButton *declineButton = [[UIButton alloc] initWithFrame:CGRectMake(66, 5, 60, 34)];
    [acceptButton setTitle:@"A" forState:UIControlStateNormal];
    [declineButton setTitle:@"D" forState:UIControlStateNormal];
    [acceptButton addTarget:self action:@selector(acceptButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    [declineButton addTarget:self action:@selector(declineButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:acceptButton];
    [view addSubview:declineButton];
    return view;
}

I have tried to debug it, but the methods are called appropriately.

2

There are 2 answers

0
flizana On BEST ANSWER

Finally, the problem was not in the cellForRowAtIndexPath: method, but in the setAccessoryViewForCell: method. When creating a view for containing two buttons as subviews I really should not have used literal values for the frames. Instead of setting a view for accessoryView property, I rewrote the whole cellForRowAtIndexPath: method and added a subview to the cell's contentView.

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
    static NSString *identifier = @"notificationsCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
    }
    PFObject *user = [self.objects objectAtIndex:indexPath.row];
    NSString *firstName = [user objectForKey:@"firstName"];
    NSString *lastName = [user objectForKey:@"lastName"];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", firstName, lastName];

    UIView *view = [UIView new];
    view.frame = CGRectMake(230, 2, 80, 40);
    view.backgroundColor = [UIColor whiteColor];

    UIButton *acceptButton = [UIButton buttonwithType:UIButtonTypeCustom];
    UIButton *declineButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [acceptButton setTitle:@"" forState:UIControlStateNormal];
    [declineButton setTitle:@"" forState:UIControlStateNormal];
    [acceptButton setImage:[UIImage imageNamed:@"Ok.png"] forState:UIControlStateNormal];
    [declineButton setImage:[UIImage imageNamed:@"Close.png"] forState:UIControlStateNormal];
    [acceptButton addTarget:self action:@selector(acceptButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    [declineButton addTarget:self action:@selector(declineButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    acceptButton.frame = CGRectMake(CGRectGetMinX(view.bounds), CGRectGetMinY(view.bounds), CGRectGetWidth(view.bounds)/2, CGRectGetHeight(view.bounds));
    declineButton.frame = CGRectMake(CGRectGetMidX(view.bounds), CGRectGetMinY(view.bounds), CGRectGetWidth(view.bounds)/2, CGRectGetHeight(view.bounds));

    [view addSubview:acceptButton];
    [view addSubview:declineButton];
    [cell.contentView addSubview:view];

    return cell;
 }

The main difference was that when setting the frames for each button, I used literal values (not a good practice) and now I used the CGRect functions CGRectGetMinX(CGRect rect), CGRectGetMinY(CGRect rect), CGRectGetWidth(CGRect rect), CGRectGetMidX(CGRect rect) and CGRectGetHeight(CGRect rect) to get more accurate values for setting each button's frame. This was a misunderstanding of how a UIView's frames work, I recommend always to use these functions to get the origin and size of subviews and not to use literal values.

1
ldindu On

The problem appeared to be you are not returning the UIView from setAccessoryViewForCell method.

return view;

Please return the view from the mentioned method, it might solve your problem.