Can't get insertion control in UITableView - iphone

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;
}

Related

Can't select UITableViewCell when TableView setEditing is set

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];
}

how to do the cell editing in the table view without making any changes in the design of the cell?

I have an application in which I am keeping my tableview as editable to drag and drop cells. But when I am doing that the design of the cell is changing such that every element is become centered and there is a right disclosure button of three lines. I need to do this by keeping the same design of the cell.without having any disclosure button and keeping the cell layout same as it is in the case of noneditable table view.I am implemented the editing like this [tableview setEditing:YES animated:YES]; in the didload and implemented the delegates as
- (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleNone;
}
- (BOOL) tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
NSInteger sourceRow = sourceIndexPath.row;
NSInteger destRow = destinationIndexPath.row;
id object = [array objectAtIndex:sourceRow];
[array removeObjectAtIndex:sourceRow];
[array insertObject:object atIndex:destRow];
}
Can anybody help me in acheiving this?
Give this a try:
Add this method to your tableView delegate to prevent indentation:
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
Then in your UITableViewCell subclass set all reordering views' alpha to 0:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated{
[super setEditing:editing animated:animated];
if (editing) {
for (UIView * view in self.subviews) {
NSLog(#"%#",view);
if ([NSStringFromClass([view class]) rangeOfString: #"Reorder"].location != NSNotFound) {
for (UIView *sv in view.subviews) {
sv.alpha = 0.0f;
}
}
}
}
}
Please note that this is a hack and I'm not sure if apple would reject the app over this.
You should return NO to this method of the tableViewDatasource:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

Temporarily Remove un-Editable Cells UITableView

I have this code implemented in my tableView:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return NO;
}
return YES;
}
It does what I want, but I want to go one step better and make "section 0" disappear altogether when the edit button is pressed (this effect can be seen if you go into the "keyboard" menu on iOS and select edit in the top right corner, the top two sections disappear in an animation). I have attempted to temporarily remove the first section, but my app crashes when [tableView reloadData]; is called:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tvController.editing == YES) {
return 1;
}else if (tvController.editing == NO) {
return 2;
}
return 0;
}
Also, I do not think I will end up with an animation if I get that code working, I think my approach is wrong. Thanks for your help guys!
Your problem
One of your sections is longer than the preceding one.
Since you hide section 0 by reporting 1 less section in numberOfSectionsInTableView:, in editing mode every delegate method must adjust the section number. One of them is not doing so.
// every delegate method with a section or indexPath must adjust it when editing
- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
if (tvController.editing) section++;
return [[customers objectAtIndex:section] count];
}
- (UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
int section = indexPath.section;
if (tvController.editing) section++;
id customer = [[customers objectAtIndex:section] indexPath.row];
// etc
}
My approach
UITableView reloadSections:withRowAnimation: reloads specified sections with an animation. Call it from your setEding:animated: delegate method.
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
UITableViewRowAnimation animation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone;
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:animation];
[self.tableView reloadSectionIndexTitles];
self.navigationItem.hidesBackButton = editing;
}
Your delegate also needs indicate that the hidden section has no rows or title.
- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.editing && section == 0) {
return 0;
}
return [[customers objectAtIndex:section] count];
}
- (NSString*) tableView:(UITableView*) tableView titleForHeaderInSection:(NSInteger) section
{
if (self.editing && section == 0) {
return nil;
}
[[customers objectAtIndex:section] title];
}

Adding dynamic sub-rows by selecting tableview row in tableview iPhone errors?

I want to add row dynamically. I have tableview list of building names. If some one choose building(didSelectRowAtIndexPath) then respective floors of building should get added dynamically as subrow. Its like maximizing and minimizing the subrow on respective building list selection. How do I do this. Thanks in advance...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// There is only one section.
if (tableView == indoortable || tableView == indoortable_iPad)
{
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of time zone names.
if (tableView == indoortable || tableView == indoortable_iPad)
{
return [indoorZones count];
}
}
cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == indoortable || tableView == indoortable_iPad)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleGray; //cell bg
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Set up the cell.
//cell.textLabel.text = [copyListOfItems objectAtIndex:indexPath.row];
cell.textLabel.text =[indoorZones objectAtIndex: indexPath.row];
//[cell setIndentationLevel:[[self.indoorZones objectAtIndex:indexPath.row] intValue]];
return cell;
}
}
didSlectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
zonesFloor = [[NSMutableArray alloc]init];
zonesFloorA = [[NSArray alloc] initWithObjects:#"Gr fl",#"1st fl",#"2nd fl",nil];
[zonesFloor addObject:zonesFloorA];
if (tableView == indoortable )
{
NSUInteger i=indexPath.row+1;
for (NSArray *count in self.indoorZones) //app is crashing here giving error.......Collection <__NSArrayM: 0x4b1d550> was mutated while being enumerated.
{
[zonesFloor addObject:[NSIndexPath indexPathForRow:i inSection:0]];
[self.indoorZones insertObject:zonesFloor atIndex:i++];
}
[[self indoortable] beginUpdates];
[[self indoortable] insertRowsAtIndexPaths:(NSArray *)zonesFloor withRowAnimation:UITableViewRowAnimationNone];
[[self indoortable] endUpdates];
}
if (tableView == indoortable_iPad )
{
//some logic
}
[tableView deselectRowAtIndexPath:selectedIndexPath animated:NO];
}
It Gives following error [__NSArrayI compare:]: Or [NSIndexPath _fastCStringContents:]: unrecognized selector sent to instance. I tried many ways but may be I am lacking somewhere. Please suggest. thanks in advance.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSIndexPath *selectedIndexPath = [self.indoortable indexPathForSelectedRow];
zonesFloorA = [[NSArray alloc] initWithObjects:#"Gr fl",#"1st fl",#"2nd fl",nil];
if (tableView == indoortable )
{
for (NSString *str in zonesFloorA) {
[indoorZones addObject:str];
}
//[[self indoortable] beginUpdates];
//[[self indoortable] insertRowsAtIndexPaths:(NSArray *)zonesFloor withRowAnimation:UITableViewRowAnimationNone];
//[[self indoortable] endUpdates];
}
if (tableView == indoortable_iPad )
{
//some logic
}
[tableView reloadData];
}
may this meet your requirement
Okay, so not to sound mean, but there are almost too many issues here to count.
Let's start with a basic explanation of how tableView's work so that you can start to fix this:
First, the tableView asks how many sections are in the table by calling:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
}
In your code, you simply tell it that it has one section. However, in your later code, when you try to add rows to your table, you tell it that you want to add your rows to a second section (with an index of 1). Therefore, you either need to add these rows to section 0 instead, or update the above method to tell it that, sometimes, there are two sections.
Second, the tableView asks how many rows are in each section of the table by calling:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
}
In your code, you are simply returning the number of zones. However, like above, you need to include the rows that you have added to your table. If you are adding them to a different section, then you need to return different values, depending on how many rows are in the section with the index asked for in the section variable. If they are all in the same section, then you need to add them up and return the correct value.
Third, the tableView asks for an actual cell for the row by calling:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
}
In your code, you are only returning a cell which has data populated by the indoorZones array, but you also need to supply cells which are configured properly for the specific zone/floor. Again, you either need to determine this by section number or row number as appropriate.
Finally, when you click on a row, the tableview tells you by calling the following method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
In this method, you need to update your data source that is used by the previous functions so that when they get called again, they will provide the correct data. Your data source must mirror the way that you want your table view to look. In your case, you have an array called indoorZones. This is good if you just want to display a list of zones, which is what you start off doing. However, when you want to add more rows, you need to add more rows to your data source first, so that when the tableView starts this process over, it is already there.
If you want everything to stay in one section, then I would come up with a data source that can include both types of rows, and be able to distinguish between them so that cellForRowAtIndexPath can create the proper type of cell and return it.
If you want two sections, then I would add a second array for the second section (since it is not the same type of data) and return the appropriate values in each of these methods, based on which array you need to use for that section.
I hope this helps!

UITableview section editable

there are 5 section in my tableview 1)1 and 2 are not editable while 3,4,and 5 are editable
in section 1 am using checkbox,2 radio box , 3 insert cell , 4 delete cell ,5 move cell
so for last 3 i want my tableview will be come editable and sign of + and - will be shown in starting of cell.
and not for forst 2 section.
i tried - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
but this is not working. any help please?
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
NSInteger section = [indexPath section];
if (section ==0)
return NO;
if (section ==1)
return NO;
if (section ==2)
return YES;
if (section ==3)
return YES;
if (section ==4)
return YES;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
[tableView reloadData];
}
You're on the right track with tableView:canEditRowAtIndexPath:. You'll also want to implement tableView:editingStyleForRowAtIndexPath:.
Also, are you calling setEditing:animated on your UITableView to put the table into editing mode? I assume you are, but it never hurts to double-check.