Can't select UITableViewCell when TableView setEditing is set - iphone

I want to be able to select multiple rows like the default mail app shown below:
I have a button called edit that calls
[self.myTableView setEditing:YES animated:YES]
The edit button successfully shows the circles on the left of the cells like the mail app as shown above. However, when I actually select one of the rows, nothing happens. The red checkmark does not appear in the circle as I would expect. Why isn't the red checkmark appearing?
#pragma mark - UITableViewDataSource Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"];
}
cell.textLabel.text = #"hey";
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
#pragma mark - UITableViewDelegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return 3;
}
#pragma mark - Private Methods
- (IBAction)editButtonTapped:(id)sender {
if (self.myTableView.editing) {
[self.myTableView setEditing:NO animated:YES];
}
else {
[self.myTableView setEditing:YES animated:YES];
}
}

You have to explicitly set selection to be enabled during editing mode:
[self.tableView setAllowsSelectionDuringEditing:YES];
Or
[self.tableView setAllowsMultipleSelectionDuringEditing:YES];
According to the docs: these properties are set to NO by default.
If the value of this property is YES , users can select rows during
editing. The default value is NO. If you want to restrict selection of
cells regardless of mode, use allowsSelection.
Additionally, the following snippet of code may be causing problems with your selection because it immediately deselects the row as soon as it's been selected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

Related

Need to enable UITextField in row of UITableView when cell is selected in iOS

I have created a custom cell that places a UITextField in each row of a UITableView. What I would like to do is enable the UITextField for a particular row (i.e. activate the cursor in that textfield), when the user presses on anywhere inside the cell.
I have the following method where I try to do this:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_cell.textField setUserInteractionEnabled:TRUE];
}
However, this is not working. Can anyone see what I'm doing wrong?
You're on the right track placing this inside didSelectRowAtIndexPath:. However, setting user interaction enabled on the textfield just means that the user would be allowed to interact with the object if they tried. You're looking for becomeFirstResponder.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell.textField becomeFirstResponder];
}
Try this code:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_cell.textField becomeFirstResponder];
}
What is this _cell iVar? Are you setting it somewhere?
I think what you are trying to accomplish is this:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell.textField becomeFirstResponder];
}
Notice that in this way you are getting the cell for the tapped indexPath.
And also, just for information, it's a pattern in objective-C to use booleans as YES or NO, instead of true or false.

TableView cell for row at index path is not beeing called every time

I have created a class to generate tickets and when the ticket is generated I want to show it in the table view one by one.
I have created a protocol for that class and once the ticket is prepared I send a message to its delegate which is tableView to reload the table view.
when the reload method is called on the tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section is being called every time a new ticket is generated but the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is not being called every time the ticket is generated but once all the tickets are generated it is being called
below is the code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.ticketGenerator == nil) {
return 0;
}
else{
return self.ticketGenerator.ticketNumbers.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
HSEticketView *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[HSEticketView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell Tickets:[self.ticketGenerator.ticketNumbers objectAtIndex:indexPath.row]];
}
// Configure the cell...
return cell;
}
//to increase the height of the cell
- (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 135;
}
-(void)background
{
[self.ticketGenerator GenerateNoOfTickets:[self.enteredNo.text intValue]:self];
}
- (IBAction)done:(id)sender {
[self.enteredNo resignFirstResponder];
self.enteredNo.hidden = YES;
self.label.hidden = YES;
self.button.hidden = YES;
self.tableView.hidden = NO;
[self performSelectorInBackground:#selector(background) withObject:nil];
NSLog(#"dgf");
}
#pragma ticketGenrate delgate methods
-(void)generationOfTicketCompleated
{
[self.tableView reloadData];
}
All changes to the UI must be done on the main thread. If you execute
[self.ticketGenerator GenerateNoOfTickets:...]
on a background thread and (as I assume) that functions calls
[tableView insertRowsAtIndexPaths:...]
that will not work, because insertRowsAtIndexPaths must be called on the main thread.
If you want to update the table view from a background thread, you can for example do
dispatch_async(dispatch_get_main_queue(), ^{
add item to data source array ...;
[tableView insertRowsAtIndexPaths:...];
});
check your return self.ticketGenerator.ticketNumbers.count; is 0 then cellForRowAtIndexPath is not call or reload your tableview in ViewWillAppear like [reload YourTableViewName].
Thank u Martin
the problem is I am doing the [tableView reloadData] on another thread as uielements need to be run on main thread the method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
is not being called the solution i got is
-(void)generationOfTicketCompleated
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}

How to highlight a row in a UITableView

The code below seems to have no effect. I want it to be highlighed in the same way it highlights when you tap on a row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[cell.textLabel setHighlighted:YES];
return cell;
}
This line will handle repainting the cell, label and accessory for you:
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
As others have noted, you can programmatically select a cell using this method:
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
However, you should be careful not to call this method too soon.
The first time that the view controller containing said tableView is initialized, the earliest that you should call this method is within viewDidAppear:.
So, you should do something like this:
- (void)viewDidAppear:(BOOL)animated
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; // set to whatever you want to be selected first
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
If you try putting this call into viewDidLoad, viewWillAppear:, or any other early view lifecycle calls, it will likely not work or have odd results (such as scrolling to the correct position but not selecting the cell).
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection: 0];
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
usually works
If you are using interface builder to build your interface, one thing to check is that you specified the view of the table view controller. If you don't actually specify the view, this selection message may go nowhere.
(you specify the view by selecting the table view controller in the interface builder inspector window and dragging the outlet for "view" to the table view you want to do the selection in).
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
// do something here
}
Try this :)
You can useĀ 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[cell.textLabel setHighlighted:YES];
return cell;
}
You have two choices. Either use the selection of the table view:
[tableView selectRowAtIndexPath: indexPath animated: YES scrollPosition: UITableViewScrollPositionNone];
Or change the background color of the table cell in the table view delegate:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = ...
}

Can't get insertion control in UITableView

I've searched all over the web, and my code seems to be nearly identical to everything out there, but I can't get my UITableView editing to work for inserting a row. When I click the edit button, all of my existing rows get the delete control, but I get no additional row for insertion. I'm pulling my hair out for what seems like it should be a simple thing. What am I missing?
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[categoryTV setEditing: editing animated:animated];
NSIndexPath *ip = [NSIndexPath indexPathForRow:[[appDelegate appCategories] count] inSection:0];
[self.categoryTV beginUpdates];
if (editing) {
[categoryTV insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationLeft];
} else {
[categoryTV deleteRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationFade];
}
[self.categoryTV endUpdates];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
if (indexPath.row >= [[appDelegate appCategories] count])
cell.textLabel.text = NSLocalizedString(#"New Category", #"NewCategoryCellText");
else
cell.textLabel.text = [[[appDelegate appCategories] objectAtIndex:indexPath.row] detailValue];
....
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.editing) {
return [[appDelegate appCategories] count] + 1;
} else {
return [[appDelegate appCategories] count];
}
}
As noted, I forgot to include my version of the suggested method, now shown below. Thanks.
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == [[appDelegate appCategories] count]) {
return UITableViewCellEditingStyleInsert;
} else {
return UITableViewCellEditingStyleDelete;
}
}
You need to implement the following delegate method to assign an editing style:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleInsert;
}
Obviously you will only return that for the cell you want to have an insert control. Otherwise, you will need to return UITableViewCellEditingStyleDelete.
I saw similar behavior in my UITableView, and the problem was that my canEditRowAtIndexPath method returned NO for the insertion control row.
set tableview editing property YES
- (void)viewDidLoad {
.......
self.tableView.editing = YES; //set editing property of tableview
.......
}
editing - A Boolean value that determines whether the table view is in editing mode.
Declaration
#property(nonatomic, getter=isEditing) BOOL editing
Discussion
When the value of this property is YES, the table view is in editing
mode: The cells of the table might show an insertion or deletion
control on the left side of each cell and a reordering control on the
right side, depending on how the cell is configured. (See
UITableViewCell Class Reference for details.) Tapping a control causes
the table view to invoke the data source method
tableView:commitEditingStyle:forRowAtIndexPath:.
The default value is NO.
then return that cell in which you want to have an insert control
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleInsert;
}

AccessoryDetailDisclosureButton not deselecting after I call deselectRowAtIndexPath

In my tableview I have number of rows that have disclosure detail button accessory type, and when pressing the row or the accessory, a new view is pushed to a navigation controller. I call the deselectRowAtIndexPath at the end of the didSelectRowAtIndexPath function.
If I press the accessory button, I go to a new view, but it remains highlighted when I come back to this view (pop). The row is deselected as expected but not this. Any thoughts on how to 'unhighlight' it?
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
[self tableView:tableView didSelectRowAtIndexPath:indexPath];
}
For those who are still bothered by this and want a solution that appears to work right now, try this:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
You must reload the data FIRST and THEN select the row so that the highlight appears beneath your action sheet options.
Simply remove from your
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath;
method the statement
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
Since your table already allows selection, and you are correctly deselecting it in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
you are done, because the row will be highlighted when selected pressing the disclosure button, and deselected when tableView:didSelectRowAtIndexPath: is executed.