I have a UITableView that has 1 blank row at the top of it, and I cannot figure out why. Here is the relevant code, do you folks have any idea what's going on here?
The UITableView loads up with no content. This method is what kicks off each data refresh after:
- (IBAction)updateButton:(id)sender
{
if (questionsTextField.isFirstResponder) {
[questionsTextField resignFirstResponder];
[self assignQuestionsCount];
}
if (currentNumberOfQuestions > 0) {
// do work calculating
currentTest = nil;
currentTest = [self retrieveCurrentTest];
currentTest.numberOfQuestions = currentNumberOfQuestions;
currentTest.decimalPlacesToDisplay = 0;
currentTest.roundingBreakPoint = 0.5;
currentGradeScale = nil;
currentGradeScale = [currentTest generateGradingScale];
[scoresTableView reloadData];
}
else {
// my error handling on text boxes here....
}
}
Here is my implementation of the UITableView methods:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.currentGradeScale count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"scoresIndentifier";
static int missedTag = 1, correctTag = 2, gradeTag = 3;
UILabel *missedLabel, *correctAndTotalLabel, *letterGradeLabel;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//if a cell does not exist, get it then initialize it
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
// populate data
missedLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 100, 50)];
missedLabel.tag = missedTag;
missedLabel.font = [UIFont systemFontOfSize:14.0];
missedLabel.textAlignment = UITextAlignmentCenter;
missedLabel.textColor = [UIColor blackColor];
missedLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight |UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
[cell.contentView addSubview:missedLabel];
}
// if it does, just reassign the properties
else {
missedLabel = (UILabel *)[cell.contentView viewWithTag:missedTag];
}
missedLabel.text = [[self.currentGradeScale objectAtIndex:indexPath.row] determineLetterGrade:0.5];
return cell;
}
Thanks for the help folks, I really appreciate it.
The most obvious explanation which you've probably already considered is that the first row of the table has been set with blank data (i.e. self.currentGradeScale objectAtIndex:0 returns nil or #"" for "determined letter grade 0.5.")
If you put a breakpoint on cellForRowAtIndexPath in the debugger at the line where you assign a value to the label text is it definitely setting a non-null/non-blank value for row 0?
Also side note there is a memory leak on missedLabel - adding it as a subview to the cell will retain it so you should autorelease on alloc, or release after adding as a subview.
I had this same problem and found that there was a value in the Scroll View Size / Content Insets / Top area. See attached image. Once I set that to 0 and saved, the blank area at the top went away. I hope this helps.
Related
I am making a form within a grouped tableview. In this form I have UIswitches and textfields. But after scrolling down, the cells styles are changing.
Here is my cellForRowAtIndex
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *MyIdentifier = #"GenericCell";
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
NSString *text = nil;
if(indexPath.section == CREDENTIALS_SECTION){
if (indexPath.row == 0) {
NSLog(#"tot hier login");
UITextField *login = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
login.adjustsFontSizeToFitWidth = YES;
login.placeholder = #"example#gmail.com";
login.keyboardType = UIKeyboardTypeEmailAddress;
login.returnKeyType = UIReturnKeyNext;
login.backgroundColor = [UIColor clearColor];
login.tag = 0;
login.delegate = self;
[login setEnabled: YES];
[cell addSubview:login];
}else if (indexPath.row == 1){
NSLog(#"tot hier pass");
UITextField *pass = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
pass.adjustsFontSizeToFitWidth = YES;
pass.placeholder = #"Required";
pass.keyboardType = UIKeyboardTypeDefault;
pass.returnKeyType = UIReturnKeyDone;
pass.secureTextEntry = YES;
pass.backgroundColor = [UIColor clearColor];
pass.tag = 0;
pass.delegate = self;
[cell addSubview:pass];
}
if (indexPath.row == 0) { // Email
text = #"Email";
}
else if(indexPath.row == 1) {
text = #"Password";
}
}else if(indexPath.section == METHODS_SECTION){
UISwitch *toggleSwitch = [[UISwitch alloc]initWithFrame:CGRectMake(220, 10, 100, 30)];
toggleSwitch.tag = indexPath.row;
[toggleSwitch addTarget:self action:#selector(toggleSwitched:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:toggleSwitch];
if (indexPath.row == 0) { // Web
text = #"Web applicatie";
}
else if(indexPath.row == 1) { //Mobile
text = #"Mobiele applicatie";
}
else if(indexPath.row == 2) { //Mail
text = #"E-mail";
}
}else if(indexPath.section == PHONE_SECTION){
UITextField *phoneText = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, 185, 30)];
phoneText.adjustsFontSizeToFitWidth = YES;
phoneText.font = [UIFont fontWithName:#"Arial-BoldMT" size:18];
phoneText.keyboardType = UIKeyboardTypeNumberPad;
phoneText.delegate = self;
phoneText.textColor = [UIColor blackColor];
phoneText.text = _person.phone;
[cell addSubview:phoneText];
}else if(indexPath.section == REMARK_SECTION){
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(20, 10, 280, 260)];
textView.text = _person.remark;
textView.delegate = self;
textView.font = [UIFont fontWithName:#"Arial" size:15.0];
textView.backgroundColor = [UIColor clearColor];
[cell addSubview:textView];
text = #"";
}else if(indexPath.section == BUTTON_SECTION){
cell.backgroundColor = [UIColor redColor];
text = #"test";
}
cell.textLabel.text = text;
return cell;
}
After some searching I found that more people are having this problem. And that the problem lays in this piece of code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *MyIdentifier = #"GenericCell";
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
NSString *text = nil;
But I don't find a solution for it.
Hope anybody can help!
Kind regards!
Clarification
Oké so here you see a screenshot of my form. below I have a red cell (save button) when I scroll down other cells are getting a red background. And some cells, text property's are changing.
That is not gong to work. Aparently you did not yet fully understand how the re-use mechanism works.
What do you do?
First you fetch a cell to be re-used. If you get one -fine so far but the problem comes later. If you don't get one then you create a new one.
When you have created a new one, which is the case at start before the user begins scrolling, then you add some UIItems depending on section and row. I will explain why this is not actually a smart thing to do.
Then the user scrolls. Cells will dissappear from screen and then made available for re-use. Then you will fetch the cells for re-use. But it may well happen that those cells already have additional UI-Items on them because you have used them before in that way. In the following process you will add new UI Items regardless whether there are already additional UI-Items on that very cell.
What can you do:
Create your own custom table cell subclasses. One subclass for each set of additional ui items that you may need. That is probably the neatest way of doing it. For each subclass use a different re-use identifier (!!!)
This is what I would recommend!
However, there are alternatives:
You could still live with your concept but invent an individual type of re-use identfier for each type of cell that has some type of additional ui item on it. If so, then make sure that these UI items are only created and added as sub-views in the if (cell == nil) branch of your code. Only create them once and then re-use them. Cell reuse-IDs could be "email-display", "email-input" , "password-display", "password-input", "switch", ...
A variance of the solution above would be, to calculate row and section
into the reuse-identifier. Such as "cell-id-0.2" for section 0 and
row 2 - or so. But still you will have to make sure that you really
re-use the additional UI views and do not re-create them every time
when the cell is filled with data. Plus, the layout in your first section varies depending on whether you want to input password and e-mail or just display them. You will still have to deal with those variations.
If cell == nil - meaning if a cell is re-used - then first clean it from every UI item that you may have added before. You can do that by tagging your UIViews with - let's say 99 - (anything different from 0 should do) upon creation and when reusing enumerate over all subviews and remove those, which have the tag 99. Despite that you can stick with the code that you have already made.
The easiest fix is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"GenericCell"] ;
//some more code
return cell;
}
This would remove the reusability from the tableview, but since it's a limited settings view, it can be ok. I would still advice taking 1 or 2 from Hermann Klecker's solutions.
If you also need to persist UIControl state then use
static NSString *MyIdentifier = [NSString stringWithFormat:#"GenericCell%d",indexPath.row];
It will always return your unique table row and you can use it as required.
Try to remove all subviews from cell before reusing it. Try the code :
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;
}
else
{
[cell.contentView.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
}
Remove all subviews before adding the subviews on cell.
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier]autorelease];
}
else
{
//To remove the subview of cell.
for (UIView *vwSubviews in [cell.contentView subviews])
{
[vwSubviews removeFromSuperview];
}
}
It may solves your problem.
Actually you have some bad code here.
In the mehthod
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Unless it is not in if (cell == nil), you should NOT initialize and use any
-(void)addSubview:(UIView*)view
Why?
The cells are views which are reused from tableview. So If you add some subview, next time while reusing the cell, it will be added more subviews on it. Simply they are overlapped and may cause MEMORY LEAK.
Do not forget that cells are reusable. So;
if I have the following code unless I do not set text somewhere else. It is expected to all cells has the text in their text labels "this is a text". Because they are reusable.
if (someChangingBool) {
cell.textLabel.text = #"this is a text";
}
So I need to have an else for that if which sets the text something else.
For more Information.
This is probably caused by poor design, but when I scroll my table too fast, and then scroll back to the top, the view that is placed in the last table cell is also placed over the first table cell in the tableView.
I think it is probably caused by my use of if statements to put some static content in the first section and dynamic content in the second section.
Any help is appreciated.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if (indexPath.section == 0) {
if (indexPath.row == 0) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(10, 13, 282, 20)];
textField.clearsOnBeginEditing = NO;
textField.placeholder = #"enter template name";
textField.font = [UIFont systemFontOfSize:15.0];
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.delegate = self;
textField.text = [selectedTemplate name];
[textField addTarget:self action:#selector(nameDidChange:) forControlEvents:UIControlEventEditingChanged];
[cell.contentView addSubview:textField];
} else {
cell.textLabel.text = #"Add a new question";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
} else {
NSString *label = [[sortedQuestions valueForKey:#"questionText"] objectAtIndex:indexPath.row];
CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15] constrainedToSize:CGSizeMake(230, 9999) lineBreakMode:NSLineBreakByWordWrapping];
UITextView *textV=[[UITextView alloc] initWithFrame:CGRectMake(5, 5, 230, stringSize.height+10)];
textV.font = [UIFont systemFontOfSize:15.0];
textV.text=label;
textV.textColor=[UIColor blackColor];
textV.editable = NO;
textV.userInteractionEnabled = NO;
textV.backgroundColor = [UIColor colorWithRed:0.97f green:0.97f blue:0.97f alpha:1.00f];
[cell.contentView addSubview:textV];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
Here is what I ended up doing based on Wienke's recommendation. I added 3 prototype cells to my storyboard named Cell,Cell2,Cell3.
Relevant code:
static NSString *CellIdentifier = #"Cell";
static NSString *CellIdentifier2 = #"Cell2";
static NSString *CellIdentifier3 = #"Cell3";
UITableViewCell *cell;
if (indexPath.section == 0 && indexPath.row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
} else if (indexPath.section == 0 && indexPath.row == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2 forIndexPath:indexPath];
} else if (indexPath.section == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier3 forIndexPath:indexPath];
}
I also added this to check my dynamic cells and remove any lingering subviews that could be hanging around before adding the new subview.
if ([cell.contentView subviews]){
for (UIView *subview in [cell.contentView subviews]) {
[subview removeFromSuperview];
}
}
I know this already has an accepted answer, but I figured I would go slightly deeper into the "why" this was happening, and the solution.
In layman's terms, the UITableView refreshing was lagging with the presentation speed asked. In other words, due to the rapid scroll, the table view was expected to repopulate the content faster than it could sort through the expected cell to reuse for it's respective index (row).
The simplest solution, which Wienke touched on, is to create different cell identifiers for the first, let's say three (3) cells. This will allow the table view to be able to clearly differentiate between the 3 cells, preventing any cell misplacement.
Perhaps the best approach here would be to assign relevant cell identifiers to each cell (depending on the context and the number of cells). This way the table view knows precisely which cell (with it's respective ID) goes where. Something as simple as the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellID = [NSString stringWithFormat:#"cell%lu", indexPath.row];
__kindof UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (!cell) {
// Create your cell here.
cell = [...allocate a new cell...] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
return cell;
}
It looks like a cell that was layed out for, say, section 0 row 0 is being dequeued and used for, say, section 0 row 1, which does not replace all of the settings that were made for it when it was holding section 0 row 0 material.
You might want to consider using 3 separate cell identifiers, one for section 0 row 0, one for section 0 row 1, and one for all the rest. You'll need a preliminary set of if statements (or switch-case statements) so that you use the right identifier when calling dequeueReusableCellWithIdentifier:.
I have been trying to figure this out for a bit. I create a custom cell in its own xib file. In my view controller I have setup a table view controller with sections. The data that is being pulled into the table View is based off a fetch request controller from some core data that I have. I set up the custom cell in the cellForRowAtIndexPath function. I am creating a label for each cell within this function and populating the label with some data from the managed object. Everything seems ok when I first run. However, when I try to scroll up and down and new cells are reused the data in the labels are placed in the wrong cells. I have seen and heard this has to do with the reuse of cells. However, have not seen much examples on correcting this issue. Below is some of the code I have in my cellForRowAtIndexPath function. Let me know if any other input may be needed. Thanks for any help.
-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
/* do this to get unique value per cell due to sections. */
NSInteger indexForCell = indexPath.section * 1000 + indexPath.row + 1;
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
NSString *lastSession = nil;
UILabel *lastSessionLabel = nil;
if(cell == nil) {
lastSession = [managedObject valueForKey:#"last_session"];
[self.tableView registerNib:[UINib nibWithNibName:#"CustomCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"CustomCell"];
self.tableView.backgroundColor = [UIColor clearColor];
cell = [aTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
lastSessionLabel = [[UILabel alloc]initWithFrame:CGRectMake(410,55, 89, 35)];
lastSessionLabel.textAlignment = UITextAlignmentLeft;
lastSessionLabel.tag = indexForCell;
lastSessionLabel.font = [UIFont systemFontOfSize:17];
lastSessionLabel.highlighted = NO;
lastSessionLabel.backgroundColor = [UIColor clearColor];
cell.contentView.tag = indexForCell;
[cell.contentView addSubview:lastSessionLabel];
} else {
lastSessionLabel = (UILabel *)[cell viewWithTag:indexForCell];
}
if (lastSession && lastSession.length) {
lastSessionLabel.text = lastSession;
}
cell.textLabel.text = [NSString stringWithFormat:#"%#%#%#%#", #"Dr. ",
[managedObject valueForKey:#"first_name"],
#" " ,
[managedObject valueForKey:#"last_name"]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.editingAccessoryType = UITableViewCellAccessoryNone;
return cell;
}
** Revised Code **
Below are the changes to code: in viewDidLoad is the following:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"CustomCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"CustomCell"];
self.tableView.backgroundColor = [UIColor clearColor];
}
in -(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
NSInteger indexForCell = indexPath.section * 1000 + indexPath.row + 1;
NSLog(#"index for cell: %d",indexForCell);
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
NSString *lastSession = [managedObject valueForKey:#"last_session"];
UILabel *lastSessionLabel = nil;
if(cell == nil) {
NSLog(#"Cell is nil! %#", [managedObject valueForKey:#"first_name"]);
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CustomCell"];
self.tableView.backgroundColor = [UIColor clearColor];
}
lastSessionLabel = [[UILabel alloc]initWithFrame:CGRectMake(410,55, 89, 35)];
lastSessionLabel.textAlignment = UITextAlignmentLeft;
lastSessionLabel.tag = indexForCell;
lastSessionLabel.font = [UIFont systemFontOfSize:17];
lastSessionLabel.highlighted = NO;
lastSessionLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview:lastSessionLabel];
/* Appropriate verbiage for nil last session. */
if (lastSession && lastSession.length) {
lastSessionLabel.text = lastSession;
}
return cell;
}
I am still having issues again with the label cell text changing when I scroll for different cells. I read some where about maybe having to use the prepareForReuse function for this.
You are only fetching lastSession when you create a new cell. Try putting this line before the if(cell == nil) statement.
lastSession = [managedObject valueForKey:#"last_session"];
I.e. this:
NSString *lastSession = [managedObject valueForKey:#"last_session"];
in stead of this:
NSString *lastSession = nil;
UPDATE
You are also setting the same tag for two views:
lastSessionLabel.tag = indexForCell;
...
cell.contentView.tag = indexForCell;
Based on your code sample you should only use the first line, i.e. set the tag for the lastSessionLabel
SECOND UPDATE
You should also only call registerNib: once in your view lifecycle, e.g. in viewDidLoad, not every time you need a new cell. Furthermore, you should create a new cell if cell == nil in stead of using dequeueReusableCellWithIdentifier:. E.g.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CustomCell"];
I am trying to cycle/navigate through the UITextFields which I added as subviews to the UITableViewCells. However I am unable to get my nextResponder value in the textFieldShouldReturn: method. Can anyone advise me where my code went wrong?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* PlaceholderCellIdentifier = #"PlaceholderCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PlaceholderCellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
}
if (indexPath.row == 0) // first name
{
cell.textLabel.text = #"First Name:";
UITextField *tempFirstNameField = [[UITextField alloc]initWithFrame:CGRectMake(100, (44-18)/2, 320-100, 32)];
self.firstNameField = tempFirstNameField;
self.firstNameField.font = [UIFont systemFontOfSize:14];
self.firstNameField.tag = 1;
self.firstNameField.returnKeyType = UIReturnKeyNext;
self.firstNameField.delegate = self;
[tempFirstNameField release];
[cell.contentView addSubview:self.firstNameField];
}
else if (indexPath.row == 1) //last name
{
cell.textLabel.text = #"Last Name:";
UITextField *tempLastNameField = [[UITextField alloc]initWithFrame:CGRectMake(100, (44-18)/2, 320-100, 32)];
self.lastNameField = tempLastNameField;
self.lastNameField.font = [UIFont systemFontOfSize:14];
self.lastNameField.tag = 2;
self.lastNameField.returnKeyType = UIReturnKeyNext;
self.lastNameField.delegate = self;
[tempLastNameField release];
[cell.contentView addSubview:self.lastNameField];
}
return cell;
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField;
{
NSInteger nextTag = textField.tag + 1;
NSLog(#"next tag %i",nextTag);
// Try to find next responder
UIResponder* nextResponder = [textField.superview.superview viewWithTag:nextTag];
//This always returns me null value
NSLog(#"next responder %#", nextResponder);
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
Why do you need a tableView for that, your fields seem to be static. Use a simple scrollview if the content is larger than you screen.
To loop your fields you can :
1/ use a container view for all controls you want in your navigation loop and simply loop in your subviews NSArray
2/ best choice. Use the NSUInteger tag field to set the order in which the controls should get the focus. Begin at non-zero value because 0 is the default tag value. 10,11,12,13 and use viewWithTag: on your container view to retrieve the next control.
UITableView is not an array - it may reload or even release any cell when it's invisible.
If you would like to operate created cells - it's better to create them all, put in an array and then display them from the array. I.e. create them all before table start loading, but not in cellForRowAtIndexPath method. It may be done in ViewWillAppear, for example.
In this case all of your objects will be retained by the array and not released until you wish to.
Got a strange problem where I'm putting some text into a cell (using cell.textLabel) and a small "tick" graphic to the right of the cell. When I select the cell, the tick is supposed to appear, or disappear if it's already there. What actually happens is the tick appears then fades out again almost instantly. It's all pretty standard code, so if anyone's got any idea what's going on I'd be pleased to hear!
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
} else {
while ([[cell.contentView subviews] count] > 0) {
UIView *labelToClear = [[cell.contentView subviews] objectAtIndex:0];
[labelToClear removeFromSuperview];
}
}
NSString *theName = [[contacts objectForKey:[contactsKeys objectAtIndex:section]] objectAtIndex:row];
cell.textLabel = theName;
if (section == 0) {
cell.textLabel.textAlignment = UITextAlignmentCenter;
} else {
cell.textLabel.textAlignment = UITextAlignmentLeft;
}
if ([selectedContacts containsObject:theName]) {
CGFloat cellRight = tableView.frame.size.width - 70;
UIImage *theTickImage = [UIImage imageNamed:#"Tick.png"];
UIImageView *theTickImageView = [[[UIImageView alloc] initWithImage:theTickImage] autorelease];
theTickImageView.frame = CGRectMake(cellRight, 10, theTickImage.size.width, theTickImage.size.height);
[cell.contentView addSubview:theTickImageView];
}
return cell;
}
Many thanks for any help!
Well, I've figured it out - the cell.textLabel was sitting on top of my graphic, so obscuring it. I just set the backgroundColor property of the textLabel to [UIColor clearColor] and all was well - maybe I could have made my graphic sit on top of the textLabel, I haven't tried that yet.