Add UIButton to UITableViewCell in case search has no results, empty array - ios

I got the following code to show a button on first UITableViewCellin case the NSArray with the search results is empty. Now, my numberOfRowsInSection has NSArray + 1, this way, my table will always have, at least, one cell.
This is in my cellForRowAtIndexPath:
if ([cell.contentView viewWithTag:1]) {
[[cell.contentView viewWithTag:1] removeFromSuperview];
}
if ((self.searchDisplayController.isActive && indexPath.row == [self.searchResults count]) || (!self.searchDisplayController.isActive && indexPath.row == [[self pegarObjetosUnicos] count])) {
// Create UIButton
UIButton *botaoProcurar = [UIButton buttonWithType:UIButtonTypeRoundedRect];
botaoProcurar.frame = CGRectMake(0, 0, 320, 50);
botaoProcurar.showsTouchWhenHighlighted = YES;
[botaoProcurar setTitle:#"Procurar no Banco de Dados" forState:UIControlStateNormal];
botaoProcurar.tag = 1;
[botaoProcurar addTarget:self action:#selector(botaoProcurar) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:botaoProcurar];
cell.textLabel.text = #"";
return cell;
}
The code first removes a subview, in case it finds one, and then create and add the button as subviewin case the search array is empty.
It works perfectly, I don't have any problems with this code, but since I need to do something similar now, I'm just wondering if this is the best approach. I'm just not comfortable with running this code for every cell my tableview has to render. I thought about adding the button to the NSArray when the database connection returned empty, but still, it wouldn't be a nice code.
Any suggestions for a more objective and clean code would be great. If not, a "Go for it! you are doing fine", will work as well. :)

You should place the button in the header or footer of the tableview. If the array has results, Remove the footer or header of the tableview. If the array has no results add the view to the footer or header. You should place this code in your function that decides if the array has data or not. This way the placement of the UIBUtton is not cell dependent, so now you won't have to run it for each and every cell you will have in the tableview.

Related

Change UIButton for Specific cell

Having issues updating uibutton in specific uitableviewcell. When I change the button color it updates every button in uitableview. Attached my code below:
PFObject *post = [self.objectArray objectAtIndex:indexPath.section];
cell.likeBtn.layer.cornerRadius = 5.0f;
//To access button methods
[cell.likeBtn setTag:indexPath.section];
NSMutableDictionary *attributes = [NSMutableDictionary
dictionaryWithDictionary:[[TMMemoryCache sharedCache] objectForKey:post.objectId]];
BOOL likedByCurrentUser = [[attributes objectForKey:#"likedByCurrentUser"] boolValue];
if (likedByCurrentUser) {
cell.likeBtn.backgroundColor = [UIColor flatRedColor];
[cell.likeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[cell.likeBtn setTitle:#"Liked" forState:UIControlStateNormal];
}else{
//NSLog(#"Did not like %#", post.objectId);
cell.likeBtn.backgroundColor = [UIColor flatBlueColor];
[cell.likeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[cell.likeBtn setTitle:#"Like" forState:UIControlStateNormal];
}
is their a better way to update uibutton in just one specific cell?
There are two ways to do what you want, depending on how the updated information comes in:
When configuring the cell in cellForRowAtIndexPath:.
Let the cell manage its own contents.
More often than not, #1 is the way to go. When new information comes into your UITableViewController, do 1 of the following:
Call reloadData to force a refresh of the entire table.
Figure out which cells need to be updated and call reloadRowsAtIndexPaths:withRowAnimation: passing in the correct index path values.
In either of those scenarios, you'll set up the button correctly somewhere in your tableView:cellForRowAtIndexPath: method. Generally, I create my UITableViewCell subclasses to accept an object and configure themselves with the data in that object. That way, there's less code in my UITableViewController that deals with cell configuration.
A typical implementation of tableView:cellForRowAtIndexPath: looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Cell *cell = [tableView dequeueReusableCellWithIdentifier:#"item" forIndexPath:indexPath];
[cell configureForItem:self.dataSource[indexPath.row]];
return cell;
}
Each of your UITableViewCell instances will have their own button that will be configured by the data passed by the object in self.dataSource[indexPath.row]. That way, as cells are recycled, the button isn't just passed around, but a new one is recycled and configured each time a new cell is needed.
At a guess, without seeing more of your code I would say your issue is with your use of indexPath.section instead of indexPath.row
If you have multiple buttons per section then they will all be covered by this code.

Dynamic button title inside a UITableView

I try to display a tableView with a button on each cell. The title of each button is a variable (an ID) in order to keep this value.
NSString *valuebutton = [NSString stringWithFormat:#"%#", [contactInfoDict objectForKey:#"idparse"]];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y + 12, 300,35);
[button addTarget:self action:#selector(customActionPressed:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor= [UIColor clearColor];
[button setTitle:valuebutton forState:UIControlStateNormal];
[cell.contentView addSubview:button];
return cell;
When I try to scroll the tableview on the device the value of the button change and I can see it be modified in live.
Did you see this issue before ?
Thanks for your help !
Alex.
Without more details it is difficult to debug. However, if you are using dynamic cells then any off screen cells are candidates for being recycled. If you use static cells, then any off screen cells are retained (not recycled). It is possible that off screen cells are being reused (assuming you are using dynamic cells) producing the behavior you described. If you are having issues with your cellForRowAtIndexPath method then that could be the issue too. Please share that code.
Also, looking at your initial code, you might want consider a dynamic prototype cell that includes the button in IB. Then all you need to do is reference the cell within cellForRowAtIndexPath, grab the button of the cell and set its title via the cell indexPath (i.e. cell 0 gets title 0, cell 1 gets title 1, etc.) -- would save you a bit of code.

Creating a button for every UITableViewCell

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!
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.
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.

iOS - UIButton in selected cells of UITableView

I'm facing a paramount problem that led me almost to toss my computer out of the window.
I'm trying to create a button only on some cells, I don't have any problem about triggering the action, but when I scroll down the table and I come back to the first cells the button is created on other cells. In other words, if cells 1 and 3 are supposed to have the button, when the tableview is created they are the only ones having the button. When I scroll down and up again also cell 2, 3 and 4 have the button (there is not a specific rule). The button is also working perfectly but it is not supposed to be there!
static NSString *CellIdentifier = #"Cell";
OpinionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell= [[OpinionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
...some influent code.......
if(([[aComment objectForKey:#"TypeMsg"] intValue]==310)&&([[parentMessage objectForKey:#"TypeMsg"] intValue]==310)){
UIButton *_openReplyButton = [[UIButton alloc] initWithFrame:CGRectMake(280, 5, 20, 20)];
[_openReplyButton setImage:[UIImage imageNamed:#"reply_button.png"] forState:UIControlStateNormal];
[_openReplyButton addTarget:self action:#selector(addRowsForShowReply:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:_openReplyButton];
NSLog(#"%#", [aComment objectForKey:#"Message"]);
}
Thank you very much for your help!
This is a classic problem for UITableView. It took me ages to figure out the dequeuing and reusing process that the table view does. Here's what should fix it.
Move the code to initialize the button into the part that checks whether cell == nil. This is because you're not supposed to add subviews to cells that have just been dequeued, because you don't know whether that cell has already had the subview added to it. Also, you should either set a tag for the button or make it a property of the OpinionCell. That way you can access it later.
Then, if you have determined that the button should be visible, set cell.replyButton.hidden = NO or [cell viewWithTag:kMyButtonTag].hidden = NO. Very importantly, you should set it to be hidden in an else clause. Otherwise, the button will show on seemingly random cells.
Hope this helps!
You can use following code to remove the subviews from UITableViewCell right after when the
cell is dequeued or initialised as it will remove all its subviews or you can follow what dado728 has mentioned above.
[[cell subviews] performSelectorOnMainThread:#selector(removeFromSuperview) withObject:nil waitUntilDone:NO];

How can I embed a UISwitch into a static UITableView?

I saw this question:
UISwitch in a UITableView cell
But it seemed to be dealing with a dynamic page. I'm really just trying to create a settings page for my app and a few of the cells in the table (not all of them), require switches on the table cell. How could I do this?
Here's how it works in Interface Builder. No need for code.
Drag a UISwitch into your View Controller. It needs to be outside the
main view. Kinda just chillin' there with some other things.
Ctrl-Click on the table view cell that should have this switch, and
drag to the new Switch. See 1.
Connect the switch to the table view cell's accessoryView outlet. See 2.
Run the app and watch the switch appear in the table - done!
Note: the switch oddly does not show up in Interface builder. But it will show up when you run the app
If you also want to hook it up to an instance variable - for example so you can read its "on" property later - connect it to an outlet just like you would any other view 3, 4.
PS: Keep in mind that UISwitch on/off state is in its "on" property, not "selected". I am just adding this because it's kinda confusing.
PPS: Sorry for the oversized pix, I'm on a retina screen.
Just drag a UISwitch over to the cell that you have laid out. You can then use the assistant editor (which is awesome) to wire it up to the parent class. One tip I will give ya, if you are planning several cells that will be similar in appearance, create the first one in the section and lay it out just right, then you can increase the # of rows in that section and IB will create copies of the existing row for you.
I create a function for this case and its work good for me .. try it , first in the cell creation you could check the row you want to add a UISwitch in , for ex.
if(indexPath.row == 0)
[self createOnOffView:cell withTitle:#"Somthing" withTag:1001 defaultVal:YES];
And the function is :
- (void) createOnOffView:(UITableViewCell*) cell withTitle:(NSString*) title withTag:(int)tag defaultVal:(BOOL) defaultVal
{
CGRect rect;
cell.textLabel.text = title;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
rect = cell.contentView.frame;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
rect.origin.x = cell.frame.size.width - 20;
else
rect.origin.x = rect.size.width/2 +35;
rect.origin.y = rect.size.height/2 - 15;
rect.size.width = 60;
UISwitch *switchView = [[UISwitch alloc] initWithFrame:rect];
[cell.contentView addSubview:switchView];
[switchView addTarget:self action:#selector(didChangeSwitch:) forControlEvents:UIControlEventValueChanged];
switchView.tag = tag;
[switchView setOn:defaultVal];
[switchView release];
}
And when the value is switch is change this method will be fired .. so you can know which switch based on the tag
- (void) didChangeSwitch:(UISwitch*)switchView
{
if(switchView.tag == 1001)
{
//Do Somthing
}
if(switchView.tag == 1002)
{
//Do Somthing
}
}
Hope this will be helpful :)
You do it exactly the same way as you do in the question you linked to. There is no such thing as a "dynamic" table. The table just displays your model. Your model might be dynamic, but the tableview is not. Either way, follow the answer to that question and you will have a switch in your tableview.

Resources