iOS uitableview cell only gets selected for a moment - cocoa-touch

In my code i want to select a cell in a UITableView. I perform the selection here, but every time it should be selected it gets selected only for a moment and then it loses its selection.
What did I do wrong?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SimpleTableIdentifier"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"SimpleTableIdentifier"];
}
cell.textLabel.text = [[self tableViewArray] objectAtIndex:indexPath.row];
if(indexPath.row == self.selectedTopicIndex)
{
NSLog(#"DIE DIE DIE DIE DIE!!!");
[cell setSelected:YES];
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
[cell setSelected:YES];
}
return cell;
}

Just move your selection logic inside -tableView:willDisplayCell:forRowAtIndexPath: method.
Something like this:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == self.selectedTopicIndex)
{
NSLog(#"DIE DIE DIE DIE DIE!!!");
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
[cell setSelected:YES];
}
}

Related

How do I add spacing between a UITableView cell image/label and the separator?

I have a UITableView with UIImage images populated in the cells. I want to be able to add some spacing between each image, and the separator lines because as you can see, some of the images are really close to the separator lines.
I could just modify the images and add spacing for each image, but I'd rather not.
Attached is what I like to achieve with the red arrows.
How can I achieve this?
Thanks.
Added code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [sponsorsLogoArray count];
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView respondsToSelector:#selector(setSeparatorInset:)])
{
[tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:#selector(setLayoutMargins:)])
{
[tableView setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:#selector(setLayoutMargins:)])
{
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [ [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set cell background color to be transparent as it cannot be achieved via storyboard
cell.backgroundColor = [UIColor clearColor];
// Populate each cell with image from array
cell.imageView.image = [UIImage imageNamed:[sponsorsLogoArray objectAtIndex:indexPath.row]];
return cell;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
return indexPath;
}

UITableViewCell update image on willDisplayCell

I am trying to update the second last row of a tableview just after the last one (of the same kind) has been inserted. What I want is to change the image in a custom uiimageview i put in the xib.
I achieved this feature by calling [_tableView reloadData] just after the insertion, but this way the insert animation has gone and the performance have got worse.
Here is part of the code I wrote:
•in the delegate:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
[_dataSource setIsRead:(BOOL)read AtIndexPath:indexPath];
[_dataSource configureCell:(WMChatTableViewCell *)cell AtIndexPath:indexPath];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
[cell setNeedsLayout];
[cell layoutIfNeeded];
}
• in the dataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
WMMessage *message = [self messageAtIndexPath:indexPath];
/**
Message sent by the user
*/
if ([message.sender_id intValue] == [[[NSUserDefaults standardUserDefaults]valueForKey:kUserIdKey]intValue]) {
WMRightChatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:rightTextIdentifier];
if (cell == nil) {
cell = [[WMRightChatTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:rightTextIdentifier];
}
[self configureCell:cell AtIndexPath:indexPath];
return cell;
}
/**
Message sent by the recipient
*/
else{
WMLeftChatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:leftTextIdentifier];
if (cell == nil) {
cell = [[WMLeftChatTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:leftTextIdentifier];
}
[self configureCell:cell AtIndexPath:indexPath];
return cell;
}
return nil;
}
-(void)configureCell:(WMChatTableViewCell *)cell AtIndexPath:(NSIndexPath *)indexPath{
WMMessage *message = [self messageAtIndexPath:indexPath];
....
/**
Last message sent by the recipient
*/
if (!([message.sender_id intValue] == [[[NSUserDefaults standardUserDefaults]valueForKey:kUserIdKey]intValue]) &&
[message isEqual:[[_messagesMatrix lastObject]lastObject]]) {
/**
An highlighted version of the background.
Normally the left cell has the "BoxChat_sx" image, only when it's the last one, the image should change
*/
[cell.balloonImageView setImage:[UIImage imageNamed:#"BoxChat_sx_new"]];
....
}
else if(!([message.sender_id intValue] == [[[NSUserDefaults standardUserDefaults]valueForKey:kUserIdKey]intValue])){
/*
If it's not the last anymore, the image should change back to it's original state
*/
[cell.balloonImageView setImage:[UIImage imageNamed:#"BoxChat_sx"]];
...
}
}
Without calling [_tableView reloadData] this code won't update the imageView. Is there a way to achieve this feature without calling reloadData or, at least, keeping the insertion animation?

Add disclosure indicator arrow to the cells in search display controller

Question: How do I add disclosure indicator arrow to the cells in my search display controller?
In a TableView you would simply set up a prototype cell but it doesn't seem to be as straight forward for the cells inside a search display controller.
BELOW IS THE TABLE VIEW CODE:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [dangerousItems count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"DangerousCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [dangerousItems objectAtIndex:indexPath.row];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
[self performSegueWithIdentifier: #"showDangerousItemDetail" sender: self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showDangerousItemDetail"]) {
DangerousGoodsDetailViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
destViewController.dangerousItemName = [searchResults objectAtIndex:indexPath.row];
destViewController.dangerousItemImage = [dangerousImage objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.dangerousItemName = [dangerousItems objectAtIndex:indexPath.row];
destViewController.dangerousItemImage = [dangerousImage objectAtIndex:indexPath.row];
}
}
}
UISearchDisplayController has a searchResultsDataSource property, which is a regular UITableViewDataSource. You are responsible for providing its implementation (typically, that's the original view controller to which the search display controller is attached).
The data source must implement tableView:cellForRowAtIndexPath:. This is where you produce cells that represent results of the search. When you create a cell that needs a disclosure indicator, add that indicator in the accessory view before returning the cell from the method.

How to keep selection of untouched cells intact?

I have a tableView where I select cells and add the data in an array, I also have the option of swiping and then deleting a particular cell which eventually deletes the data from the array.
The problem is that once I delete a row, I lose all my selection state after I reload the table,
For that I checked again with the selection array and reselected all these cells,
BUT I am stuck at one place, Much before I actually delete a cell and reload the tableView, as soon as I swipe over a cell, selection state of all other cells also go away.
NOTE: I have two arrays, one with list of itmes to be displayed in the tableView and one with the selected items.
Here is some code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.contactList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleGray;
[cell.textLabel setTextColor:[UIColor colorWithRed:103.0/255.0 green:103.0/255.0 blue:103.0/255.0 alpha:1.0]];
[cell.textLabel setFont:[UIFont fontWithName:#"ITCAvantGardeStd-Bk" size:14.0]];
if (![[[self.contactList objectAtIndex:indexPath.row] objectForKey:#"nickName"] isEqualToString:#""])
cell.textLabel.text = [NSString stringWithFormat:#"%#",[[self.contactList objectAtIndex:indexPath.row] objectForKey:#"nickName"]];
else
cell.textLabel.text = [NSString stringWithFormat:#"%# %#",[[self.contactList objectAtIndex:indexPath.row] objectForKey:#"firstName"],[[self.contactList objectAtIndex:indexPath.row] objectForKey:#"lastName"]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected cell index==>%d\n",indexPath.row);
//NSString *emailID = [NSString stringWithFormat:#"%#",[[self.contactList objectAtIndex:indexPath.row] objectForKey:#"email_key"]];
NSLog(#"emailID==>%#\n",[self.contactList objectAtIndex:indexPath.row]);
[self.emailShareList addObject:[self.contactList objectAtIndex:indexPath.row]];
//[self.emailShareList insertObject:emailID atIndex:indexPath.row];
NSLog(#"Array value==>%#\n",self.emailShareList);
//[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"deSelected cell index==>%d\n",indexPath.row);
NSString *emailID = [NSString stringWithFormat:#"%#",[[self.contactList objectAtIndex:indexPath.row] objectForKey:#"email_key"]];
NSLog(#"emailID==>%#\n",emailID);
[self.emailShareList removeObject:[self.contactList objectAtIndex:indexPath.row]];
NSLog(#"deSelect row Array value==>%#\n",self.emailShareList);
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
if(indexPath.row != 0)
{
NSString *contactID = [[self.contactList objectAtIndex:indexPath.row] objectForKey:#"contactId"];
NSLog(#"content on delete row==>%#\n",contactID);
[self.contactList removeObjectAtIndex:indexPath.row];
[self deleteContactToServer:contactID];
}
}
[contactTableView reloadData];
for (int i = 0; i < [self.emailShareList count]; i++)
{
for (int j = 0; j < [self.contactList count]; j++)
{
if([[[self.contactList objectAtIndex:j] valueForKey:#"email"] isEqualToString: [[self.emailShareList objectAtIndex:i] valueForKey:#"email"]])
{
NSIndexPath *path1 = [NSIndexPath indexPathForRow:j inSection:0];
[contactTableView selectRowAtIndexPath:path1 animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCellEditingStyle style = UITableViewCellEditingStyleNone;
if(indexPath.row != 0)
style = UITableViewCellEditingStyleDelete;
return style;
}
When you delete an item, you don't necessary have to reload the entire tableview. You could use the – deleteRowsAtIndexPaths:withRowAnimation: method to just remove the cell in question (along with an according model update). This will probably retain your selection.
To keep your selections when entering editing mode (swipe for delete is a special case of editing mode as well) you nee to do two things:
First, enable allowsSelectionDuringEditing on your tableView:
self.tableView.allowsSelectionDuringEditing = YES;
Second, create a UITableView subclass and override setEditing:animated: like this:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
NSArray *indexPaths = self.indexPathsForSelectedRows;
[super setEditing:editing animated:animated];
for (NSIndexPath *ip in indexPaths) {
[self selectRowAtIndexPath:ip animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Personally, I would rather use some sort of custom selection mechanism, when selections are important from a model point of view. I would create a custom cell subclass, add a selection property to it let it change the cell styling accordingly. The build-in features that affect regular table view selections won't cause problems with such an approach.
Here is an additional method of preserving table selections in and out of edit mode without having to subclass UITableView. Add the following to your UITableViewControllerView.
Within viewDidLoad add:
self.tableView.allowsSelectionDuringEditing = YES;
Then override setEditing:animated:
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
NSArray *selectedIndexPaths = [self.tableView indexPathsForSelectedRows];
[super setEditing:editing animated:animate];
for (NSIndexPath *selectedIndexPath in selectedIndexPaths) {
[self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}

putting limitation for checkbox in UITableView Objective-C

I create table programmatically with different sections and rows, i create check box inside table with pictures as a box
I want to put limitation for this check box
would you please help me
Edit :
my question is how can I choosing just one check box- limitation of choice
and also how can I unselect a box and remove the checkmark
here is code for check box row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *key = [[self sectionKeys] objectAtIndex:[indexPath section]];
NSArray *contents = [[self sectionContents] objectForKey:key];
NSString *contentForThisRow = [contents objectAtIndex:[indexPath row]];
if (indexPath.section != 2) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.textLabel.text =contentForThisRow;
return cell;
}
else {
CheckBoxAbsenceTableViewCell *cell = (CheckBoxAbsenceTableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"CheckBoxAbsenceTableViewCell"];
cell.imageView.image=[UIImage imageNamed:#"emptycheck-box.png"];
cell.checkBox.image = image;
if(indexPath.row == 0){
cell.absenceCode.text =#"Red";
}
else if (indexPath.row == 1){
cell.absenceCode.text =#"Green";
}else if(indexPath.row == 2){
cell.absenceCode.text =#"Blue";
}
return cell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CheckBoxAbsenceTableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
selectedCell.checkBox.image =[UIImage imageNamed:#"checkmark.png"];
}
Thanks in advance!
The easy solution is to add a UIInteger _selectedIndex instance var to your view controller.
In viewDidLoad set it to -1 (non of the rows is selected)
Then when user select a cell, save the selected index and reload the tableView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selectedIndex = indexPath.row;
[self.tableView reloadData];
}
Change the cellForRowAtIndexPath method so it will select only the selected cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *key = [[self sectionKeys] objectAtIndex:[indexPath section]];
NSArray *contents = [[self sectionContents] objectForKey:key];
NSString *contentForThisRow = [contents objectAtIndex:[indexPath row]];
if (indexPath.section != 2) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.textLabel.text =contentForThisRow;
return cell;
}
else {
CheckBoxAbsenceTableViewCell *cell = (CheckBoxAbsenceTableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"CheckBoxAbsenceTableViewCell"];
if (indexPath.row == _selectedIndex) {
cell.checkBox.image =[UIImage imageNamed:#"checkmark.png"];
}
else {
cell.checkBox.image = [UIImage imageNamed:#"emptycheck-box.png"];;
}
if(indexPath.row == 0){
cell.absenceCode.text =#"Red";
}
else if (indexPath.row == 1){
cell.absenceCode.text =#"Green";
}else if(indexPath.row == 2){
cell.absenceCode.text =#"Blue";
}
return cell;
}
}
From a UI design perspective, you should be using the cell.accessoryType and the UITableViewCellAccessoryCheckmark accessory.
You need to keep track of the selected (i.e. checked) indexPath in your data model. Lets call this self.idxPathSelected.
This didSelectRowAtIndexPath will add checkmark to the selected row, and clear checkmark from the previously selected row:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if (self.idxPathSelected != nil)
{
cell = [tableView cellForRowAtIndexPath:self.idxPathSelected];
cell.accessoryType = UITableViewAccessoryNone;
}
self.idxPathSelected = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
}
and in your cellForRowAtIndexPath, something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if ((self.idxPathSelected != nil) && ([self.idxPathSelected compare:indexPath] == NSOrderedSame))
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
...
}