Incorrect text positioning in UITableViewCell in Xcode when creating cells programatically - objective-c

I have created a UITableView with two cells, username and password using the code below. I am doing this programatically as static cells can't be used in a UIViewController (where this table must reside)
I have included a screenshot of the output the first time the view loads (the expected output) and the second time the view is shown (the incorrect output)
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:#"Cell"];
if( cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Login Ident"];
if (indexPath.row == 0) {
loginId = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
loginId .placeholder = #"Email address";
loginId .autocorrectionType = UITextAutocorrectionTypeNo;
[loginId setClearButtonMode:UITextFieldViewModeWhileEditing];
cell.accessoryView = loginId;
}
if (indexPath.row == 1) {
password = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
password.placeholder = #"Password";
password.secureTextEntry = YES;
password.autocorrectionType = UITextAutocorrectionTypeNo;
[password setClearButtonMode:UITextFieldViewModeWhileEditing];
cell.accessoryView = password;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
loginId.delegate = self;
password.delegate = self;
[loginId setText:[keychain objectForKey:(__bridge id)kSecAttrAccount]];
[password setText:[keychain objectForKey:(__bridge id)kSecValueData]];
[loginId addTarget:self
action:#selector(textFieldReturn:)
forControlEvents:UIControlEventEditingDidEndOnExit];
[password addTarget:self
action:#selector(textFieldReturn:)
forControlEvents:UIControlEventEditingDidEndOnExit];
[cell.contentView addSubview:loginId];
[cell.contentView addSubview:password];
//[_tableView addSubview:loginId];
//[_tableView addSubview:password];
}
return cell;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[_tableView reloadData];
}
My UITextField declarations
UITextField *loginId;
UITextField *password;
If anybody is able to help me out with this, I'd really appreciate it.

Looks like you are having issues with your cell reuse.
Here is how I would do it:
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Login Ident";
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:identifier];
if (nil == cell) {
// Within this if statement do any work that is not going to change over the lifetime of the cell.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
// You was setting `selectionStyle` on every run so it should be
// safe to set here once
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
const NSInteger textFieldTag = 10; // <- No special meaning, just non-zero
UITextField *textField = (UITextField *)[cell viewWithTag:textFieldTag];
// I've followed a similar pattern to the cell reuse above for creating the textfield
// This ensures that we only create a textfield once per cell and then reuse it
if (nil == textField) {
textField = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
textField .autocorrectionType = UITextAutocorrectionTypeNo;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.delegate = self;
textField.tag = textFieldTag;
[cell addSubview:textField];
}
// Next do any work to configure the different cells
if (indexPath.row == 0) {
textField.placeholder = #"Email address";
cell.accessoryView = loginId;
textField = textField;
loginId = textField;
} else if (indexPath.row == 1) {
textField.placeholder = #"Password";
textField.secureTextEntry = YES;
cell.accessoryView = password;
password = textField;
}
// ... rest of your work
return cell;
}

This is a issue because of the cell reusing. you need to change your cell a bit: add a textLabel in the if(cell==nil) branch, but configure it as username or password outside of the branch.

Firstly, the section:
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:#"Cell"];
if( cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Login Ident"];</code>
should be
static NSString *identifier = #"Login Ident";
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:identifier];
if( cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];</code>
Secondly, creating your text fields should be done outside the if (cell == nil) section.

Related

UITableView if(cell == null) error

I have this problem with my code, I am trying to add textfields to my cells. And it worked! But when I tried again afterwards it didn't. I debugged a little with NSLog and came to the conclusion that cell wasn't = nil and therefore my code wasn't being run.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Called1");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"Called?");
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
if([indexPath row] == 0) {
playerTextField.placeholder = #"yoyo1";
playerTextField.keyboardType = UIKeyboardTypeDefault;
playerTextField.returnKeyType = UIReturnKeyNext;
} else {
playerTextField.placeholder = #"yoyo2";
playerTextField.keyboardType = UIKeyboardTypeDefault;
playerTextField.returnKeyType = UIReturnKeyDone;
playerTextField.secureTextEntry = YES;
}
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.autocorrectionType = UITextAutocorrectionTypeNo;
playerTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
playerTextField.textAlignment = UITextAlignmentLeft;
playerTextField.tag = 0;
playerTextField.clearButtonMode = UITextFieldViewModeNever;
[playerTextField setEnabled: YES];
[cell.contentView addSubview:playerTextField];
}
return cell;
}
The code NSLog(#"Called?") doesn't get called, but NSLog(#"Called1") does. Why?
Thanks.
Just a little change:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Called1");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"Called?");
//And then the rest of your cell configuration code...
Update your code to this, the way you initialize table cells is not correct.
[tableView dequeueReusableCellWithIdentifier:#"Cell"]; if this line returns non-nil your code will not correctly initialize the table cell. The logic is to get a new table cell by either dequeuing or re-using after you allocated a suitable table cell decorate it the same way.
-(UITableViewCell *)reuseTableViewCellWithIdentifier:(NSString *)identifier withIndexPath:(NSIndexPath *)indexPath{
UITableViewCell * cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
return cell;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Called1");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [self reuseTableViewCellWithIdentifier:#"Cell" withIndexPath:indexPath];
}
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"Called?");
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
if([indexPath row] == 0) {
playerTextField.placeholder = #"yoyo1";
playerTextField.keyboardType = UIKeyboardTypeDefault;
playerTextField.returnKeyType = UIReturnKeyNext;
} else {
playerTextField.placeholder = #"yoyo2";
playerTextField.keyboardType = UIKeyboardTypeDefault;
playerTextField.returnKeyType = UIReturnKeyDone;
playerTextField.secureTextEntry = YES;
}
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.autocorrectionType = UITextAutocorrectionTypeNo;
playerTextField.autocapitalizationType = UITextAutocapitalizationTypeNone;
playerTextField.textAlignment = UITextAlignmentLeft;
playerTextField.tag = 0;
playerTextField.clearButtonMode = UITextFieldViewModeNever;
[playerTextField setEnabled: YES];
[cell.contentView addSubview:playerTextField];
return cell;
}

Adding label color close to each row in UITableView Objective-C

I have a UITableView with different sections and rows. I want to have different label or image like a icone close each cell but I don't know why it's looks like this picture:
Also scrolling changed the size of labels!
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *key = [[self sectionKeys] objectAtIndex:[indexPath section]];
NSArray *contents = [[self sectionContents] objectForKey:key];
NSString *contentForThisRow = [contents objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
if(indexPath.row == 0)
{
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(3,0,40,40)];
label.backgroundColor = [UIColor darkGrayColor];
[cell.contentView addSubview:label];
}
else if(indexPath.row == 1)
{
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(3,0,40,40)];
label.backgroundColor = [UIColor redColor];
[cell.contentView addSubview:label]; }
else if(indexPath.row == 2)
{
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(3,0,40,40)];
label.backgroundColor = [UIColor redColor];
[cell.contentView addSubview:label]; }
else{
}
[[cell textLabel] setText:contentForThisRow];
return cell;
}
In your code when user scroll table, labels created many times! You must check if color label already exist in cell and then set color
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
int colorLabelTag = 9999;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Because table cells are reusing we must check is label already in cell
UILabel* label = (UILabel *) [cell viewWithTag:colorLabelTag];
// If no - we create label
if (!label) {
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(3,0,40,40)];
label.tag = colorLabelTag;
[cell addSubview:label];
}
if(indexPath.row == 0)
{
label.backgroundColor = [UIColor darkGrayColor];
}
else if(indexPath.row == 1)
{
label.backgroundColor = [UIColor redColor];
}
else if(indexPath.row == 2)
{
label.backgroundColor = [UIColor redColor];
}
[[cell textLabel] setText:contentForThisRow];
return cell;
Unless you want more cusotomizing than this there is no need for subclassing the cell.
Let me give it a try:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *key = [[self sectionKeys] objectAtIndex:[indexPath section]];
NSArray *contents = [[self sectionContents] objectForKey:key];
NSString *contentForThisRow = [contents objectAtIndex:[indexPath row]];
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
// If you need to add more custom views then create them here. E.g.:
UILabel *myLable = [[UILabel alloc] initWithFrame:CGRectMake(10,200,20,20)];
myLable.text = #"Some Value";
label.tag = 101; // use anything but 1. Better use a constant expression.
[cell.contentView addSubview:myLable];
}
switch (indexPath.row) {
case 1:
cell.imageView.image = [UIImage imageNamed:#"red.png"];
break;
case 2:
cell.imageView.image = [UIImage imageNamed:#"blue.png"];
break;
case 3:
cell.imageView.image = [UIImage imageNamed:#"green.png"];
break;
}
UILabel* theLabel = (UILabel *) [cell viewWithTag:101]; // again, a constant is of better style here.
if (theLabel { // it must exist. However, it is good practice to check upon that.
label.text = #"someOtherValue";
}
[[cell textLabel] setText:contentForThisRow];
// you may need to layout your subviews here.
return cell;
}

UITableView Custom View still here even after reload

I made a very simply table view, with load more function.
I have added a custom view on the last cell with text "Load More"
After the user clicked the load more function, the rows increased successfully.
But the text "Load More" didn't disappear.
Please help.
Here is my code.
- (void)viewDidLoad {
[super viewDidLoad];
noRow = 10;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return noRow+1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (indexPath.row != noRow ) { // As long as we haven’t reached the +1 yet in the count, we populate the cell like normal
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
NSString *cellValue = [[NSNumber numberWithInt:[indexPath row]] stringValue];
cell.text = cellValue;
} // Ok, all done for filling the normal cells, next we probaply reach the +1 index, which doesn’t contain anything yet
else if(indexPath.row == noRow ) { // Here we check if we reached the end of the index, so the +1 row
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
UILabel *loadMore;
loadMore =[[UILabel alloc]initWithFrame: CGRectMake(0,0,320,50)];
loadMore.textColor = [UIColor blackColor];
loadMore.highlightedTextColor = [UIColor darkGrayColor];
loadMore.backgroundColor = [UIColor clearColor];
loadMore.font=[UIFont fontWithName:#"Verdana" size:20];
loadMore.textAlignment=UITextAlignmentCenter;
loadMore.font=[UIFont boldSystemFontOfSize:20];
loadMore.text=#"Load More..";
[cell addSubview:loadMore];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == noRow){
NSLog(#"noRow Prev: %d", noRow);
noRow += 5;
NSLog(#"noRow After: %d", noRow);
[self.tableView reloadData];
}else{
NSLog(#"IndexPath.row: %d", indexPath.row);
}
}
You are reusing the and you are not removing the view that you have added for load more
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[[cell viewWithTag:121] removeFromSuperview];//remove this tag view
if (indexPath.row != noRow ) { // As long as we haven’t reached the +1 yet in the count, we populate the cell like normal
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
NSString *cellValue = [[NSNumber numberWithInt:[indexPath row]] stringValue];
cell.text = cellValue;
} // Ok, all done for filling the normal cells, next we probaply reach the +1 index, which doesn’t contain anything yet
else if(indexPath.row == noRow ) { // Here we check if we reached the end of the index, so the +1 row
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
UILabel *loadMore;
loadMore =[[UILabel alloc]initWithFrame: CGRectMake(0,0,320,50)];
loadMore.textColor = [UIColor blackColor];
loadMore.highlightedTextColor = [UIColor darkGrayColor];
loadMore.backgroundColor = [UIColor clearColor];
loadMore.font=[UIFont fontWithName:#"Verdana" size:20];
loadMore.textAlignment=UITextAlignmentCenter;
loadMore.font=[UIFont boldSystemFontOfSize:20];
loadMore.text=#"Load More..";
loadMore.tag = 121;// just setting the tag
[cell addSubview:loadMore];
}
return cell;
}
you should add loadMore as a subview to cell.contentView not cell.
after that add this line in your cellForRow ..
for (UIView *view in [cell.contentView subviews])
{
[view removeFromSuperview];
}
Currently your load more is being reused and is present in subsequent cells if reused.

Incorrect text positioning in UITableViewCell in Xcode

I have created a UITableView with two cells, username and password using the code below.
I have included a screenshot of the output the first time the view loads (the expected output) and the second time the view is shown (the incorrect output)
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:#"Cell"];
if( cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Login Ident"];
if (indexPath.row == 0) {
loginId = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
loginId .placeholder = #"Email address";
loginId .autocorrectionType = UITextAutocorrectionTypeNo;
[loginId setClearButtonMode:UITextFieldViewModeWhileEditing];
cell.accessoryView = loginId;
}
if (indexPath.row == 1) {
password = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
password.placeholder = #"Password";
password.secureTextEntry = YES;
password.autocorrectionType = UITextAutocorrectionTypeNo;
[password setClearButtonMode:UITextFieldViewModeWhileEditing];
cell.accessoryView = password;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
loginId.delegate = self;
password.delegate = self;
[loginId setText:[keychain objectForKey:(__bridge id)kSecAttrAccount]];
[password setText:[keychain objectForKey:(__bridge id)kSecValueData]];
[loginId addTarget:self
action:#selector(textFieldReturn:)
forControlEvents:UIControlEventEditingDidEndOnExit];
[password addTarget:self
action:#selector(textFieldReturn:)
forControlEvents:UIControlEventEditingDidEndOnExit];
[cell.contentView addSubview:loginId];
[cell.contentView addSubview:password];
}
return cell;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[_tableView reloadData];
}
My UITextField declarations
UITextField *loginId;
UITextField *password;
If anybody is able to help me out with this, I'd really appreciate it.
With changes
You should put the code where you create the text fields inside the if (cell == nil) {} since otherwise you could be adding a second textfield to a cell that's already been created previously. If that doesn't fix the issue post back.
Also, remove:
[_tableView addSubview:loginId];
[_tableView addSubview:password];
You shouldn't add views that are meant for the cells to the tableview. And instead of making it the accessoryView of the cell, add them to the contentView
[cell.contentView addSubview:loginId];
See chat below for full resolution of the issue.

Making UITableView without IB

I'm making UITableView without IB.
My UITableView has 2 styles UITableViewCell - first row style and other row style.
I use MTLable Class instead of UILabel.
Question:
This code's results is very strange.
First cell style and other cell style is mixed when next page scrolled.
I can't find my code's faults.
I need your advice. Thanks!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//firsT cELL
if(indexPath.row==0)
{
CGRect frame=CGRectMake(0,0,80, 60);
MTLabel *label1=[[MTLabel alloc] init];
label1.backgroundColor = [UIColor grayColor];
label1.frame=frame;
label1.text=#"123";
label1.tag = 1001;
[cell.contentView addSubview:label1];
label1.autoresizingMask = UIViewAutoresizingFlexibleTopMargin &UIViewAutoresizingFlexibleWidth & UIViewAutoresizingFlexibleLeftMargin & UIViewAutoresizingFlexibleRightMargin;
label1.contentMode = UIViewContentModeTopLeft;
[label1 setTextAlignment:MTLabelTextAlignmentRight];
[label1 release];
}
else
{
CGRect frame3=CGRectMake(0,0,80, 60);
MTLabel *label3=[[MTLabel alloc]init];
label3.frame=frame3;
label3.backgroundColor = [UIColor purpleColor];
label3.text=#"100";
label3.tag = 1003;
label3.autoresizingMask = UIViewAutoresizingFlexibleTopMargin &UIViewAutoresizingFlexibleWidth & UIViewAutoresizingFlexibleLeftMargin & UIViewAutoresizingFlexibleRightMargin;
label3.contentMode = UIViewContentModeTopLeft;
[label3 setTextAlignment:MTLabelTextAlignmentRight];
[cell.contentView addSubview:label3];
[label3 release];
}
}
FTS_book *book = [items objectAtIndex:indexPath.row];
if(indexPath.row==0)
{
MTLabel *label1 = (MTLabel*)[cell viewWithTag:1001];
label1.text= [NSString stringWithFormat:#"%d", book.chapter];
}
else
{
MTLabel *label3 = (MTLabel*)[cell viewWithTag:1003];
label3.text= [NSString stringWithFormat:#"%d", book.verse];
}
return cell;
}
Use different cell Id's for those two styles.