2 UITableView in a UIViewController affecting each other - ios

I've been going at this for about 3 hours now, and I'm finally throwing in the towel to y'all. I have 2 UITableViewin my view, one of which is a forum board to leave comments and what not, and the second UITableView is used to mention people. the issue I am having is that both tableview counts are being affected even if i only want to update just 1 of the tableviews.
I set the delegate/datasource in the viewdidload
self.mentionTableView.delegate = self;
self.mentionTableView.dataSource = self;
self.mentionTableView.tag = 1;
self.forumTable.delegate = self;
self.forumTable.dataSource = self;
self.forumTable.tag = 2;
and if i actually do not load feedArray which is where forumTable gets its data from, the mention portion works perfectly. I've figured out that if matchedNames.count<feedArray.count everything works fine, but if matchedNames.count>feedArray.count it crashes and this is the error i get
-[__NSCFArray objectAtIndex:]: index (1) beyond bounds (1)
which means that i only have 1 item in feedArray and matchedNames has more than one.
inside of
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
i have used these codes to try to make it work and still nothing, ive even done combinations of them.
1)
if ([tableView isEqual: mentionTableView]){
NSLog(#"%#",matchedNames);
NSLog(#"%i",matchedNames.count);
return [matchedNames count];
} else if([tableView isEqual:forumTable]){
return [feedArray count];
}
2)
if (tableView == mentionTableView){
NSLog(#"%#",matchedNames);
NSLog(#"%i",matchedNames.count);
return [matchedNames count];
} else if(tableView == commentTable){
return [feedArray count];
}
3)
if (tableView.tag == 1){
NSLog(#"%#",matchedNames);
NSLog(#"%i",matchedNames.count);
return [matchedNames count];
} else if(tableView.tag == 2){
return [feedArray count];
}
and I know I didnt have to do the else if but I was just trying to be specific to maybe avoid this issue.
this is my cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.tag == 1){
CGAffineTransform transform = CGAffineTransformMakeRotation(3.14);
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.transform = transform;
cell.textLabel.text = [self.matchedNames objectAtIndex:indexPath.row];
return cell;
} else {
static NSString *CellIdentifier = #"commentCell";
commentsCustomCell *cell =(commentsCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[commentsCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSDictionary *feedPost = [feedArray objectAtIndex:indexPath.row];
NSString *checkIFempty = [feedPost objectForKey:#"isForum_empty"];
if (![checkIFempty isEqualToString:#"1"]) {
cell.noCommentsLabel.text = nil;
} else {
cell.noCommentsLabel.text = #"No Comments";
cell.forumComment = nil;
}
NSString *username =[feedPost objectForKey:#"Username"];
NSString *final_time =[feedPost objectForKey:#"final_time"];
NSString *userIDforPic =[feedPost objectForKey:#"UserID"];
finalComment = [feedPost objectForKey:#"comment"];
cell.forumComment.text = finalComment;
return cell;
}
}
if my question is confusing i do apologize, I haven't slept 36 hours. thanks for looking at my question!

You really really really should consider to refactor your code and separate this two tableViews in different viewControllers.
You can, for example, use containerViews inside your main viewController and put the tableview in the container view controllers.
TableView delegates use a lot of code, and set different tableViews to the same controller will always end up like this, messing the code and giving more trouble than it should be.

There are a few techniques you can use that will help clean up your code and allow for a less messy solution. I will take a wack at explaining this.
One first easy step is to create a property or method that gives you the array of data based on the tableView or tag:
- (NSArray *)dataForInteger:(NSUInteger)value {
return #[self.matchedNames, self.feedArray][value];
}
// you can also make this a readonly property for easier access
In order to use the above method you need to make sure the tag for the table that needs matchedNames is 0 and feedArray is 1 (or you could use a simple if/else statement and make the tags whatever you want.
Now look how easy this makes your future logic!
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
[[self dataForInteger:tableView.tag] count];
}
That's it!
Next, you could potentially create a method like:
- (UITableViewCell *)emptyCellForTableView:(UITableView *)tableView {
NSString *cellIdentifier = #[#"CellIdentifierONe", #"CellIdentifierTWO"][tableView.tag];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
// the only messy looking logic
if (!tableView.tag) { // tableView.tag == 0
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
CGAffineTransform transform = CGAffineTransformMakeRotation(3.14);
cell.transform = transform;
} else {
// make sure "CommentsCustomCell" is a class and not an instance (like your example)
cell = [[CommentsCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
}
return cell;
}
Then in your tableView:cellForRowAtIndexPath::
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self emptyCellForTableView:tableView];
NSArray *dataArray = [self dataForInteger:tableView.tag];
// setup all custom UITableViewCell's to have a property or setter "data"
if ([cell respondsToSelector:#selector(setData:)]) {
// I will explain this a bit later
cell.data = dataArray[indexPath.row];
} else {
// based on your example this was an NSString array
self.textLabel.text = dataArray[indexPath.row];
}
}
Now the cell.data = dataArray[indexPath.row]; is per Apple's example how setup data for custom UITableViewCells. Just create a property called data, that takes in it's setter looks something like this (for your example):
// CommentsCustomCell.m
- (void)setData:(id /*or custom class, in this case you use NSDictionary*/)data {
_data = data;
// NTOE: I just copied your example above, I am sure there is a nicer way to do this but you get the idea.
NSDictionary *feedPost = (NSDictionary *)data;
NSString *checkIFempty = [feedPost objectForKey:#"isForum_empty"];
if (![checkIFempty isEqualToString:#"1"]) {
cell.noCommentsLabel.text = nil;
} else {
cell.noCommentsLabel.text = #"No Comments";
cell.forumComment = nil;
}
NSString *username =[feedPost objectForKey:#"Username"];
NSString *final_time =[feedPost objectForKey:#"final_time"];
NSString *userIDforPic =[feedPost objectForKey:#"UserID"];
finalComment = [feedPost objectForKey:#"comment"];
cell.forumComment.text = finalComment;
}
The reason why a solution like this is so beautiful is if you ever wanted to use a different custom UITableViewCell all you would need to do is change the Empty Cell Creation method to create that class, and that is basically it (This also allows you to make all of your cell's IBOutlets private!). As long as the new class has a data property your main controller does not care! It just sends the data through. This also allows you to scale it appropriately. If all the tableView's used custom cells you could easily have a dozen tableviews in the same viewController without needing much extra logic (just add it the array, set the tag, and make sure the cell creation method creates the appropriate cell!).
I typed this up pretty quickly so there is probably some missing logic or typos. I will fix any if they are pointed out. Good luck.

Related

UITableView DataSource must return a cell from cellforRowAtIndexPath Error

I have two different tableViews in one view controller and I get an error message. The data source and delegate are set to the view controller. Am I doing something wrong in the tableview methods. I haven't dealt with more than one tableView in the same view before. Thanks
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
if (tableView == self.postsTableView) {
return 1;
}
else if (tableView == self.eventsTableView){
return 1;
}
return 1;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (tableView == self.postsTableView) {
return 1;
}
else if (tableView == self.eventsTableView){
return 1;
}
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tableView isEqual: self.postsTableView]) {
profilePagePostCell *cellOne = (profilePagePostCell *) [tableView dequeueReusableCellWithIdentifier:#"profilePostCell"];
cellOne.postLabel.text = [NSString stringWithFormat:#"Hi"];
return cellOne;
}
if ([tableView isEqual: self.eventsTableView]) {
profileEventCell *cellTwo = (profileEventCell *) [tableView dequeueReusableCellWithIdentifier:#"profileEventCell"];
cellTwo.eventLabel.text = [NSString stringWithFormat:#"The big One"];
return cellTwo;
}
profileEventCell *cell = (profileEventCell *) [tableView dequeueReusableCellWithIdentifier:#"profileEventCell"];
return cell;
}
Unless you have already called registerClass:forCellReuseIdentifier: or defined a prototype class in your nib or storyboard on your UITableView, you're going to get nil cells back from that dequeReusableCellWithIdentifier: call. You can register one if you like, or you can create a local instance when you have received nil, making sure to call UITableViewCell initWithStyle:reuseIdentifier: as your initialization method.
I'm not seeing any immediate problems in your code. I assume those cells are registered properly in either a prototype cell or by registering them in code. If not then that is probably the issue. I would put a breakpoint in your cellForRowAtIndexPath: and step through the process to make sure its even being called for one, and make sure that it is in fact returning a cell. Make sure that the cell is not nil in all of your cases.
Not enough information but two among several reasons:
(1) You've not registered the two custom cells before trying to deque them.
If this is the case, register them while overridng viewDidLoad like follows.
[self.postsTableView registerClass:[profilePagePostCell class] forCellReuseIdentifier:#"profilePostCell"];
or
[self.postsTableView registerNib:#"YOUR_NIB_NAME" forCellReuseIdentifier:#"profilePostCell"]
(2) The identifier names you're using in cellForRowAtIndexPath method do not match what you registered in viewDidLoad method.
Double check the names and I strongly recommend you to use defined constant name in order to get support from Xcode.
You don't alloc memory for cells. Try this code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath(NSIndexPath *)indexPath{
static NSString *cellIdentifierPosts = #"cellIdentifierPosts"
static NSString *cellIdentifierEvents = #"cellIdentifierEvents"
if ([tableView isEqual: self.postsTableView]) {
profilePagePostCell *cellOne = (profilePagePostCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifierPosts];
if (!cellOne)
cellOne = [[profilePagePostCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: cellIdentifierPosts];
cellOne.postLabel.text = [NSString stringWithFormat:#"Hi"];
return cellOne;
}
else if ([tableView isEqual: self.eventsTableView]) {
profileEventCell *cellTwo = (profileEventCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifierEvents];
if (!cellTwo)
cellTwo = [[profileEventCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: cellIdentifierEvents];
cellTwo.eventLabel.text = [NSString stringWithFormat:#"The big One"];
return cellTwo;
}
else{
profileEventCell *cell = (profileEventCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifierEvents];
if (!cell)
cell = [[profileEventCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: cellIdentifierEvents];
cell.eventLabel.text = [NSString stringWithFormat:#"The default One"];
return cell;
}
}

Only One Of Two UITableViews Are Loading

I have two tableviews and only the person tableview is loading data. How do i handle multiple uitableviews on one view controller? Below is what i have so far with my .m file. TABLE VIEW PERSONS is the only log return I'm getting I should also get TABLE VIEW EXPECTATIONS logged if this was working right (as well as data loading into that expectations tableview of course)
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if(tableView == self.listPersonTableView)
return 1;
else if(tableView == self.listExpectationsTableView)
return 1;
else
return 0;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if(tableView == self.listPersonTableView)
return [arrayOfPersons count];
else if(tableView == self.listExpectationsTableView)
return [arrayOfExpectations count];
else
return 0;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if(tableView == self.listPersonTableView){
Person *person = [arrayOfPersons objectAtIndex:indexPath.row];
cell.textLabel.text = person.personName;
NSLog(#"TABLE VIEW PERSONS");
return cell;
}
else if(tableView == self.listExpectationsTableView){
Expectations *expectation = [arrayOfExpectations objectAtIndex:indexPath.row];
cell.textLabel.text = expectation.expText;
NSLog(#"TABLE VIEW EXPECTATIONS");
return cell;
}
else
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == _listPersonTableView) {
NSLog(#"Row In Person TableView Selected Nothing To Do HERE YET");
}
else if(tableView == self.listExpectationsTableView){
NSLog(#"Row In Expectations TableView Selected Nothing To Do HERE YET");
}else{
NSLog(#"Do Nothing");
}
}
EDIT: So from comments below i have found that my arrayOfExpectations is 0 but don't know why. See my while loop below. I know its looping twice because the NSLog is showing twice but with 0 as the array count?
while (sqlite3_step(statement)==SQLITE_ROW){
NSString *expText = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement,4)];
NSString *expID = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement,3)];
NSString *efeID = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement,0)];
Expectations *expectations = [[Expectations alloc]init];
[expectations setExpText:expText];
[expectations setExpID:expID];
[expectations setEfeID:efeID];
[arrayOfExpectations addObject:expectations];
NSLog(#"Expectations Count: %lu", (unsigned long)[arrayOfExpectations count]);
}
I had this same problem once. I check every single thing to see why the table was not getting populated. I checked the Delegate and DataSource of the UITableView is connected. Array has data in it. And every possible thing to display the data, but in vain. Then i just tried and used tags for UITableViews, and I dont know how but it worked. It somehow worked. Since that day I used tags for UITableView and I never had to look back.
You can try the same.
if (tableView.tag == 1){
...Do something here...
}
Try and check. Hope this works for you as it did for me. Cheers. :)
I have had this problem before. This could be caused by the NSMutableArray is not allocated and initialized. Make sure you have arrayOfExpectations = [[NSMutableArray alloc] init]; somewhere in your code.

How to skip over empty labels in UITableViewCells

My cell.textLabel.text sometimes returns an empty string. Is there a way I can skip this cell and put my next text label right after my last non empty cell.textLabel.text? So there should no empty labels.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
}
ResultModel *resultModel = [self.array objectAtIndex:indexPath.row];
cell.textLabel.text = resultModel.resultString;
return cell;
}
cell.textLabel takes the whole content view's size.width so you calculate the length of the string and manipulate next label accordingly
Try this code.
if([resultModel.resultString isEqualToString:#""])
{
// Display the label
cell.textLabel.text = resultModel.resultString;
}
else
{
//result string is Null do nothing here.
}
Why don't you just get instances which have value in "resultString" property?
NSArray *dataWithResultString = [call the custom method to get instances with no empty value];
ResultModel *resultModel = [dataWithResultString objectAtIndex:indexPath.row];
This you should handle in the datasource array itself...
Populate a new array with values having the resultModel.resultString and use this array as the datasource for tables
if i understand you correctly you want the cell to be displayed only if there is some non empty string in resultModel.resultString, right?
For that you better handle the datasource array itself. If that's hard, you can do this.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
ResultModel *resultModel = [self.array objectAtIndex:indexPath.row];
if([resultModel.resultString isEqualToString:#""])
return 0.0;
else
return 50;//or whatever
}
But its better handling the datasource itself.
If I'm reading you right, the resulted array might return an empty string and if so, you don't want to show those rows right?
Ideally, you should've add another parameter to your query to exclude the empty resultString. However, if you want a hacky way, declare (int)padRows and set it to 0 in viewDidLoad;
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
}
ResultModel *resultModel = [self.array objectAtIndex:indexPath.row];
while([resultModel.resultString isEqualToString:#""]) {
_padRows += 1;
resultModel = [self.array objectAtIndex:(indexPath.row+_padRows)];
}
cell.textLabel.text = resultModel.resultString;
return cell;
}
Code not tested.

How to create a dynamic size array

What I am trying to achieve:
I have a UITableView and I want to check whether the table was selected or not and keep in an array easy to access the YES or NO values that corresponds to that row so that afterwards i can manipulate the data.
my code as follows
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellLabelText = cell.textLabel.text;
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
selected[row] = NO;
}
else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
selected[row] = YES;
}
}
As it stands out I can create a BOOL selected[some value] but my problem is that the max index needed for me is unknown as my table size changes constantly. thus setting the max index limits me.
I am new to objective C and I come from a PHP background thus I dont know whether it is possible to create an array that does what i want to do in objective-c.
Otherwise what would be my options within objective-c to have an easy way to easy write/read selected[row] = YES/NO.
I need a way to write YES/NO and link it to the indexpath.row
Use an NSMutableSet and store the NSIndexPath of the selected rows. If you select a row you add the path to the set. If you unselect a row, remove the path from the set.
To see if a row is selected, see if the indexPath is in the set or not.
BTW - this only works if the rows are fixed. If the user can add, remove, or reorder rows then this approach will not work. In such a case you need to store data keys, not index paths.
Create an ivar of type NSMutableSet. Let's call it selectedRows:
selectedRows = [[NSMutableSet alloc] init];
Then in didSelectRow you do:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL selected = [selectedRows containsObject:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellLabelText = cell.textLabel.text;
if (selected) {
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedRows removeObject:indexPath];
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedRows addObject:indexPath];
}
}
In your cellForRow... method you do something similar:
BOOL selected = [selectedRows containsObject:indexPath];
cell.accessoryType = selected ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
Just use
NSMutableArray *dynamicArray = [NSMutableArray array];
You can add and delete objects from this at will. Just be sure to use the NSNumber wrapper to add primitives:
[dynamicArray addObject:[NSNumber numberWithInt:indexNumber]];
// or
[dynamicArray addObject:#(indexNumber)];
Instead of an array you can use a index set.
#property (nonatomic,strong) NSMutableIndexSet *pickedIndexPaths;
- (void)viewDidLoad
{
_pickedSIndexPaths = [[NSMutableIndexSet alloc] init];
[super viewDidLoad];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//…
if(indexPath.section == 0) {
cell.textLabel.text = self.sports[indexPath.row][#"sport"][#"name"];
if ([_pickedIndexPaths containsIndex:indexPath.row]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([_pickedIndexPaths containsIndex:indexPath.row]) {
[_pickedIndexPaths removeIndex:indexPath.row];
} else {
[_pickedIndexPaths addIndex:indexPath.row];
}
[tableView reloadData];
}
}
When what you need is a variable length array of boolean values, you can use CFBitVectorRef. This will consume much less memory than using a Cocoa collection designed for objc object values (provided of course that array has many elements) because it consumes 1 bit for each value, rather than a full pointer which points to an individual dynamically allocated reference counted object.

Custom cell in UITableView is not displaying properly - only last cell is populated

Apologies if this comes across as a beginner's question. I'm trying to populate a UITableView with sections and custom cell formatting.
I've created a customCell in ViewControl.xib which sits along the main view and looks like this:
customCell image
I have a dictionary to load up the values using a method in another class, depending on which row it's at. If it's in Row 1, load details for item 1 etc.
This is the code I'm using:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"customCell"];
// assigns current row's labels
NSArray * customCellText = [Model cellText:indexPath.row];
dinnerItem.text = customCellText[0];
dinnerDescription.text = customCellText[1];
dinnerTime.text = customCellText[2];
cell = customCell;
return cell;
}
And this is currently what's being generated:
iPhone simulator screenshot
The issues I have:
It's not populating all rows, only the last one.
I can only seem to click on the row which is populated, and even then
it stays selected as opposed to 'clicking on it'.
If I drag it up or down quickly it crashes.
I presume it has to do with the way it's redrawing/populating cells?
Thanks in advance!
SineTwo
EDIT, ADDED MORE CODE FOR CLARIFICATION:
ViewController.m
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [Model countKeys];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [Model rowsInSection:section];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
// slightly crap code, this is initiated in viewDidLoad and is an array created by a method in Model.m. Only looks for keys and returns an array.
return headerKeys[section];
}
Model.m
+(NSArray *)headerKeys
{
NSArray *headerKeys = [[NSArray alloc] init];
headerKeys = [timerDictionary allKeys];
NSLog(#"All keys: %#", headerKeys);
return headerKeys;
}
+(NSArray *)customCellText
{
NSArray *customCellText = [[NSArray alloc]initWithObjects: #"dinnerItemText", #"dinnerDescriptionText", #"01:00", nil];
return customCellText;
}
+(NSInteger)rowsInSection:(NSInteger)sectionNumber
{
NSArray *keyContent = [[NSArray alloc] init];
keyContent = [timerDictionary objectForKey:dictionaryKeys[sectionNumber]];
NSLog(#"current section[%i]: %i", sectionNumber, [keyContent count]);
return [keyContent count];
}
+(NSArray *)cellText:(NSInteger)rowNumber
{
// display all dictionary keys, dictionaryKeys[x] will give back the specific category
dictionaryKeys = [timerDictionary allKeys];
// displays contents of first key in dictionary
NSArray *keyContent = [[NSArray alloc] init];
keyContent = [timerDictionary objectForKey:dictionaryKeys[0]];
// creates an array with all items within the selected key
NSArray *keyItems = [[NSArray alloc] initWithArray:keyContent[rowNumber]];
return keyItems;
}
I can say the following:
if you only do that:
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"customCell"];
prior to iOS 5 this doesn't guarantee you getting back a cell. Prior to iOS5 you have to do the following:
NSString *cellIdentifier = [NSString stringWithFormat:#"I%d-%d", indexPath.section, indexPath.row];
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// assigns current row's labels
NSArray * customCellText = [Model cellText:indexPath.row];
dinnerItem.text = customCellText[0];
dinnerDescription.text = customCellText[1];
dinnerTime.text = customCellText[2];
cell = customCell;
return cell;
}
If you are on iOS5/6 these lines are not needed anymore:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
But you have to use the following methods in the tableView setup:
registerClass:forCellReuseIdentifier: (available in iOS6 and later)
registerNib:forCellReuseIdentifier: (available in iOS5 and later)
Just hoping to solve your problem:
Don't forget the lines [...](cell == nil)[...]
First, change your method to this! You need to check if the cell is nil:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
// assigns current row's labels
NSArray * customCellText = [Model cellText:indexPath.row];
dinnerItem.text = customCellText[0];
dinnerDescription.text = customCellText[1];
dinnerTime.text = customCellText[2];
cell = customCell;
}
return cell;
}

Resources