0

I'm trying to create an friend request function. Where all the friend request would show up in a table and a player will get to click accept or decline. What I'm trying to do is create an accept button beside this UITableView that contains all the player's friend requests.

Here's my code.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *notificationCell = [tableView dequeuREusableCellWithIdentifier@"notificationCell" for IndexPath:indexPath];

    NSArray *friendRequests = [self fetchAllFriendRequestsInArray];
    NSManagedObject *friendRequestingRelationship = [friendRequests objectAtIndex:indexPath.row];
    notificationCell.textLabel.text = [friendRequestingRelationship valueForKey:@"name"];

    UIButton *acceptButton = [UiButton buttonWithType:UIButtonTypeSystem];

    [acceptButton.frame = CGRectMake(notificationCell.frame.origin.x + 150, notificationcell.frame.origin.y -20, 80, 40);
    [acceptButton setTitle:@"Accept" forState:UIControlStateNormal];
    acceptButton.backgroundColor = [UIColor clearColor];
    [acceptButton addTarget:self action:@selector(acceptButtonPressed) forControlEvents:UIControlEventTouchUpInside];

    [notificationCell.contentView addSubview:acceptButton];

    return notificationCell;
}

Only the first notificationCell showed the friendrequester's name and Accept Button. Other notificationCells only showed other friendrequesters' names without the button. May I know what is wrong with my code such that I can allow the button to be shown on every single cell?

Thank you in advance!

  • Take a look at this... http://stackoverflow.com/questions/22963192/getting-data-from-a-textfield-inside-a-prototype-uicollectionviewcell/22966470#22966470 – CrimsonChris Apr 17 '14 at 15:09
  • Since you're populating your friendRequest array within cellForRowAtIndexPath I'm assuming you don't know how many friend requests there are until reaching this method... What code do you have in numberOfRowsInSection: ? Could you post that code here? – Lyndsey Scott Apr 17 '14 at 15:09
  • @LyndseyScott my code is [[self fetchAllFriendRequestsInArray] count] – user3335395 Apr 17 '14 at 15:11
  • 2
    This has a serious problem - you add an additional button every time a cell is reused as the user scrolls the table view. – rmaddy Apr 17 '14 at 15:17
  • Hi @rmaddy, can you elaborate on that please? – user3335395 Apr 17 '14 at 15:28
  • @user3335395 My answer explains that already (point number two in the list of problems). – Sergey Kalinichenko Apr 17 '14 at 15:30
  • By the way... Cell reuse is entirely optional. If you find it too confusing to figure out right now, you can always just not do it. – CrimsonChris Apr 17 '14 at 15:41

2 Answers2

1

The buttons are there, but they are clipped from the view. This line is the culprit:

acceptButton.frame = CGRectMake(notificationCell.frame.origin.x + 150, notificationcell.frame.origin.y -20, 80, 40);

You shouldn't add the origin of notificationCell to the button, because subview positions are relative to positions of their superviews.

This should give you the right look, but your code has other potential problems.

  • The line where you fetch all friend requests is probably too slow to be executed for each cell in the view. Make sure that the results are cached
  • Table view cells are recycled. When one of such recycled cells makes it to your code, it looks like your code adds a second button on top of the first one
  • Similarly, if a recycled cell with a button is returned for the cell that does not need a button, the old button would remain visible.

You may be better off using a prototype cell that already has a button on it. Instead of adding and removing that button, you could make the existing one visible or invisible, depending on the context.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Hey @dasblinkenlight That's a very detailed answer. I tried editing the code to remove the origin.x and the button did show up. I'm now curious about 2 things: Is there any documents that I can read up on cells being recycled? How do I go about, fixing a cell with a button, instead of adding/removing? Thank you for your ever-swift reply! – user3335395 Apr 17 '14 at 15:43
  • 1
    @user3335395 You can read about this in the documentation of the `dequeueReusableCellWithIdentifier:` method of `UITableView` [here](https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#//apple_ref/occ/instm/UITableView/dequeueReusableCellWithIdentifier:) – Sergey Kalinichenko Apr 17 '14 at 15:47
  • alright, that's enlightening. Thanks for that help. So I believe I just kept adding the button as its subview every single time its being reused. Instead, I have to fix a button as part of the prototype cell instead of adding it as its subview. May I know how do I go about doing that? – user3335395 Apr 17 '14 at 15:53
  • @user3335395 [Here is a short tutorial on prototype cells](http://useyourloaf.com/blog/2012/06/07/prototype-table-cells-and-storyboards.html). The tutorial shows three labels; your code should add a button, and whatever other view elements that you need. Then you could reference the button inside you `cellForRowAtIndexPath:`, and set its visibility according to the row in which the cell is displayed. – Sergey Kalinichenko Apr 17 '14 at 15:58
0

This is a bad approach to solving this problem to begin with. You should go to the storyboard, and drop a button in a prototype cell. Then select that button, go to the attributes inspector, and set the "tag" to a number of your choice (for this example we will say 1). You can then get the button for each cell like so after grabbing the cell:

UIButton * acceptButton = (UIButton *)[cell viewWithTag: 1];
[acceptButton addTarget:self action:@selector(acceptButtonPressed) forControlEvents:UIControlEventTouchUpInside];

This is cleaner and will give you the results you want.

AdamG
  • 3,718
  • 2
  • 18
  • 28
  • Hey Adam, may I know where I can add that. When I did that, it says Incompatible pointer types initializeing "UIButton" with an expression of type "UIView" – user3335395 Apr 17 '14 at 15:23
  • Check out my changes in the first line. You have to cast the UIView pointer to a UIButton. – AdamG Apr 17 '14 at 15:53
  • Hi adam, I tried your code, but the button only shows up when I highlight/click on the cell. For example, I have 3 table cell. And only the one I highlight will display the button Accept. – user3335395 Apr 18 '14 at 07:15