Expand/collapse rows using header section in a UITableView - ios

Hello I have implemented example Expand Table
-(void)sectionButtonTouchUpInside:(UIButton*)sender
{
// sender.backgroundColor = [UIColor greenColor];
[self.tableView beginUpdates];
int section = sender.tag;
bool shouldCollapse = ![collapsedSections containsObject:#(section)];
if (shouldCollapse)
{
int numOfRows = [self.tableView numberOfRowsInSection:section];
NSArray* indexPaths = [self indexPathsForSection:section withNumberOfRows:numOfRows];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
[collapsedSections addObject:#(section)];
}
else
{
int numOfRows = 0 ;
switch (section)
{
case 0:
numOfRows = (int)aArray.count;
break;
case 1:
numOfRows = (int)bArray.count;
break;
case 2:
numOfRows = (int)cArray.count;
break;
case 3:
numOfRows = (int)dArray.count;
break;
}
NSArray* indexPaths = [self indexPathsForSection:section withNumberOfRows:numOfRows];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
[collapsedSections removeObject:#(section)];
}
[self.tableView endUpdates];
}
My program crashed in above code with this message:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of rows in section 2. The number of rows contained in an
existing section after the update (1) must be equal to the number of
rows contained in that section before the update (1), plus or minus
the number of rows inserted or deleted from that section (0 inserted,
1 deleted) and plus or minus the number of rows moved into or out of
that section (0 moved in, 0 moved out).
Update
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(![_collapsedSections containsObject:#(section)])
{
return 0;
}
else
{
int count = 0;
switch (section)
{
case 0:
count = (int)aArray.count;
break;
case 1:
count = (int)bArray.count;
break;
case 2:
count = (int)cArray.count;
break;
case 3:
count = (int)dArray.count;
break;
}
return count;
}
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0)
{
return [__collapse containsObject:#(section)] ? 0 : [self.section1 count];
}
else if(section == 1)
{
return [__collapse containsObject:#(section)] ? 0 : [self.section2 count];
}
else if(section == 2)
{
return [__collapse containsObject:#(section)] ? 0 : [self.section3 count];
}
else
{
return 0;
}
}
Modify this method like above..

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = 0;
switch (section)
{
case 0:
count = (int)aArray.count;
break;
case 1:
count = (int)bArray.count;
break;
case 2:
count = (int)cArray.count;
break;
case 3:
count = (int)dArray.count;
break;
}
return count;
}
Try this..
For Ur Code..Initially ur rows are 0. So, After u click event methods try to insert ur array no.of.rows.. Thats causing error.

Related

Reload UITableView except one section of it

I have a tableView with multiple sections.
Now I want to reload all sections of tableView except the first one (because it's static and doesn't change).
I now I can reload sections by this method:
reloadSections(IndexSet, with: UITableView.RowAnimation)
but it requires the number of sections and in my app this is dynamic and changes in time.
I can only say reload whatever exist after first section.
I thought I should define a IndexSet somehow like this:
NSIndexSet *indexSet = [NSIndexPath indexPathWithIndexes:(NSUInteger[]){1, ... } length:???];
and I don't know how can I do that!
Any ideas or suggestion would be greatly appreciated.
update
This is the numberOfSectionsInTableView implementation:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
// Inbox Segment
if (self.selectedIndex == 0) {
if (self.inboxArray.count > 0) {
return self.inboxArray.count + 2;
}
}
// Sent Segment
else if (self.selectedIndex == 1) {
if (self.sentArray.count > 0) {
return self.sentArray.count + 2;
}
}
// Outbox Segment
else if (self.selectedIndex == 2) {
if (self.outboxArray.count > 0) {
return self.outboxArray.count + 2;
}
}
// Spam Segment
else if (self.selectedIndex == 3) {
if (self.spamArray.count > 0) {
return self.spamArray.count + 2;
}
}
// Trash Segment
else if (self.selectedIndex == 4) {
if (self.trashArray.count > 0) {
return self.trashArray.count + 2;
}
}
return 1;
}
Assuming you know the amount of sections:
NSIndexSet *sectionsIndexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, self.sections.count - 1)]
[self.tableView reloadSections:sectionsIndexSet withRowAnimation:UITableViewRowAnimationNone];
Swift:
let sectionsIndexSet = IndexSet(1..<sections.count)
tableView.reloadSections(sectionsIndexSet, with: .none)

iOS - Error when adding row to UITable (Objective-C)

I'm getting this error when adding a row to a UITable.
'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 7. The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
number of elements:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self tableView:tableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return mArray[section];
}
return 1; // only top row showing
}
// Return the number of rows in the section.
return 1;
}
Counting number to be in each part:
int k = 0;
for (int i = 0; i < 28; i++) {
if ([[currentEntry objectForKey:#"item"] isEqualToString:items[i]]) {
mArray[i] += 1;
k = i;
}
}
Adding to table
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
// only first row toggles exapand/collapse
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
NSLog(#"SSection:%d", rows);
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i
inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded)
{
dispatch_async(dispatch_get_main_queue(), ^{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
});
}
Error occurs here
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
});
}
}
}
}
This error only occurs in one section which is 7. All other sections are fine
First you need add object in collection which telling tableview about count of items for appearing, create index path for new cell and make insert row with index path. Perhaps you create wrong index path.
I think your array and your numberOfRows should be matching in your 7th section.
//MARK: UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 7) {
return YOUR_ARRAY.count;
}
}

UITableView with customcell

i am developing an iPhone app with tableview that act as a form with different sections. i also have 3 custom cell that contain Text Field, Segment Control and UISwitchView. my problem is that when i pressed on of the Switches or type some text in one of the textField, the same state of the Switch or text of the text Field reappear in different row and in different section.
Here is some images and part of my code to describe my problem:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 0;
switch (section) {
case 0:
rows = 5;
break;
case 1:
rows = 11;
break;
case 2:
rows = 9;
break;
default:
break;
}
return rows;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
// init cell
switch (indexPath.section) {
case 0:
if (indexPath.row>=0 && indexPath.row<=3)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"text_field_cell"];
}
else if (indexPath.row == 4)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"segment_cell"];
}
break;
case 1:
if (indexPath.row >=0 && indexPath.row <= 9)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"switch_cell"];
}
else if (indexPath.row == 10)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"text_field_cell"];
}
break;
case 2:
if (indexPath.row >=0 && indexPath.row <= 6)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"switch_cell"];
}
else if (indexPath.row >=7 && indexPath.row <=8)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"text_field_cell"];
}
break;
default:
break;
}
// init all text ..
return cell;
}
I would implement -tableView:willDisplayCell:forRowAtIndexPath: to set your cells to a correct state for each row.

Semantic issue control may reach end of non-void function

I'm creating a recipes app and have run into this semantic issue in the number of rows in section method of my table view. This is the first time I've really worked with table Views and I'm wondering if someone could perhaps see what I've done wrong and point me in the right direction. Thanks!
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (menuInt == 0)
return [soupsArray count];
if (menuInt == 1)
return [saladsArray count];
if (menuInt == 2)
return [appetizersArray count];
if (menuInt == 3)
return [entreeArray count];
if (menuInt == 4)
return [dissertsArray count];
[self.tableView reloadData];
}
What happens if all the if conditions fail? You need to make sure that you at least return an NSInteger even though you are sure one of the if conditions will succeed for sure. That's just how it is.
Also, as Martin R pointed out, you should not have reloadData in the function.
try one of these 2 solutions (the reload data must occur before the return statement also)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int counter = 0;
// Return the number of rows in the section.
if (menuInt == 0)
counter = [soupsArray count];
if (menuInt == 1)
counter = [saladsArray count];
if (menuInt == 2)
counter = [appetizersArray count];
if (menuInt == 3)
counter = [entreeArray count];
if (menuInt == 4)
counter = [dissertsArray count];
[self.tableView reloadData];
return counter;
}
or
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (menuInt == 0) {
[self.tableView reloadData];
return [soupsArray count];
}
else if (menuInt == 1) {
[self.tableView reloadData];
return [saladsArray count];
}
else if (menuInt == 2) {
[self.tableView reloadData];
return [appetizersArray count];
}
else if (menuInt == 3) {
[self.tableView reloadData];
return [entreeArray count];
}
else if (menuInt == 4) {
[self.tableView reloadData];
return [dissertsArray count];
else {
[self.tableview reloadData];
return 0;
}
}

UITableView with multiple sections shows only one section

I have a problem which seems to be very simple. I have a UITableView in my APP. In numberOfSectionsInTableView: I set the count of sections to 2. However the tableView shows only the first section. I tried to make the two sections show same contents by writing same codes in both sections, but useless. Then I found a similar question here. But its correct answer is about frame and my layout is a very simple UITableViewController. At last I tried to add NSLog to the three methods. The result is: For case section 1, numberOfSectionsInTableView: and numberOfRowsInSection: are called but cellForRowAtIndex isn't called. I wonder how to explain this.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
int count;
switch (section) {
case 0:
count = [_objectArray count];
break;
case 1:
NSLog(#"section called"); // This line is logged
count = 1;
default:
count = 0;
break;
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"myCellIdentifier";
static NSString *basicCellIdentifier = #"myBasicCellIdentifier";
switch ([indexPath section]) {
case 0: {
TableViewStoryCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
// Configure the cell...
int theIndex = [indexPath row];
MyObject *theObj = [_objectArray objectAtIndex:theIndex];
cell.object = theObj;
return cell;
break;
}
case 1: {
NSLog(#"cell called"); //this line isn't logged
for (int i = 0; i < 50; i++) {
NSLog(#"hahaha");
}
MyBasicViewStoryCell *cell = [tableView dequeueReusableCellWithIdentifier:basicCellIdentifier forIndexPath:indexPath];
return cell;
break;
}
default: {
for (int i = 0; i < 50; i++) {
NSLog(#"hahaha1");
}
return nil;
break;
}
}
}
Put break in switch case. You missed break in case 1: so the default will also execute. Thus the count become zero count = 0. Since numberOfRowsInSection: returns zero, cellForRowAtIndexPath: will not call. So put break in case 1: of numberOfRowsInSection:
switch (section) {
case 0:
count = [_objectArray count];
break;
case 1:
NSLog(#"section called"); // This line is logged
count = 1;
break; // Here
default:
count = 0;
break;
}
You don't have a break after you set the count for section 1 and it falls through and is set to zero.
case 1:
NSLog(#"section called"); // This line is logged
count = 1;
break; // always put break!
cellForRowAtIndexPath won't be called if numberOfRowsInSection is not returning a value that is >=1.

Resources