i've been advised to create multiple subclasses for each section, since i'm creating an tableview with lots of different content, the problem is whatever i do it keep duplicating the content of each cell randomly. What am i doing wrong?
viewDidLoad
identifier0 = #"Cell0";
identifier1 = #"Cell1";
identifier2 = #"Cell2";
[self.tableView registerClass:[accountTableViewCell class] forCellReuseIdentifier:identifier0];
[self.tableView registerClass:[NotificationTableViewCell class] forCellReuseIdentifier:identifier1];
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//section 0
self.emailTextField.delegate = self;
self.cellName = [[UILabel alloc] initWithFrame:CGRectMake(20, 12, 130, 20)];
self.cellName.textColor = [UIColor colorWithRed:0.137 green:0.145 blue:0.157 alpha:1];
self.cellName.font = [UIFont fontWithName:#"HelveticaNeue" size:14];
self.nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 7, 190, 30)];
self.nameTextField.enabled = NO;
self.emailTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 7, 190, 30)];
[self.emailTextField setReturnKeyType:UIReturnKeyDone];
[self.emailTextField setKeyboardType:UIKeyboardTypeEmailAddress];
self.genderSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
//section 1
self.acceptanceSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
self.likeSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
self.messageSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
accountTableViewCell *cell0;
NotificationTableViewCell *cell1;
if(indexPath.section == 0)
{
cell0 = [tableView dequeueReusableCellWithIdentifier:identifier0 forIndexPath:indexPath];
} else if (indexPath.section == 1) {
cell1 = [tableView dequeueReusableCellWithIdentifier:identifier1 forIndexPath:indexPath];
}
// This part ensure you will initiate each cell with the correct identifier
if (!cell0)
{
cell0 = [[accountTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier0];
cell0.backgroundColor = [UIColor colorWithRed:0.953 green:0.953 blue:0.965 alpha:1] ;
} else if (!cell1) {
cell1 = [[NotificationTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier1];
cell1.backgroundColor = [UIColor colorWithRed:0.953 green:0.953 blue:0.965 alpha:1] ;
}
if (indexPath.section == 0) {
[cell0.contentView addSubview:self.cellName];
self.cellName.text = [accountArray objectAtIndex:indexPath.row];
if (indexPath.row == 0) {
[cell0.contentView addSubview:self.nameTextField];
} else if (indexPath.row == 1) {
[cell0.contentView addSubview:self.emailTextField];
} else if (indexPath.row == 2) {
[cell0.contentView addSubview:self.genderSwitch];
}
} else if(indexPath.section == 1) {
[cell1.contentView addSubview:self.cellName];
cell1.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [notArray objectAtIndex:indexPath.row];
if (indexPath.row == 0) {
[cell1.contentView addSubview:self.acceptanceSwitch];
} else if (indexPath.row == 1) {
[cell1.contentView addSubview:self.messageSwitch];
} else if (indexPath.row == 2) {
[cell1.contentView addSubview:self.likeSwitch];
}
}
return cell0;
return cell1;
}
You are seeing duplicate content because you have the custom contentView's subviews as properties of your UITableViewDataSource. For example, you use self.cellName for every cell in section 0. Let us say you have 5 cellName-type cells in section 0. If you want a custom UILabel on all 5 cells then you would need to alloc/init 5 separate UILabels for each cell and the key part is that you need 5 separate pointers for each label. Right now you are using one, self.nameLabel. There are many ways you could go about fixing this. One way would be making the custom subviews as properties of your two UITableViewCell subclasses.
Related
I'm trying to create a in app setting tableview, which requires different sections with different content. i first tried all the code outside (!cell), but that resulted in duplicate of the content on scroll, i've then found thread where it said i needed to put inside (!cell), but now it does not show any content. What am i doing wrong?
CellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
cell.backgroundColor = [UIColor colorWithRed:0.953 green:0.953 blue:0.965 alpha:1] ;
self.emailTextField.delegate = self;
self.cellName = [[UILabel alloc] initWithFrame:CGRectMake(20, 12, 42, 20)];
self.cellName.textColor = [UIColor colorWithRed:0.137 green:0.145 blue:0.157 alpha:1];
self.cellName.font = [UIFont fontWithName:#"HelveticaNeue" size:14];
[cell.contentView addSubview:self.cellName];
if (indexPath.section == 1) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [notArray objectAtIndex:indexPath.row];
if (indexPath.row == 0) {
self.acceptanceSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.acceptanceSwitch];
} else if (indexPath.row == 1) {
self.messageSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.messageSwitch];
} else if (indexPath.row == 2) {
self.likeSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.likeSwitch];
}
} else if (indexPath.section == 0) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [accountArray objectAtIndex:indexPath.row];
if (indexPath.row == 0) {
self.nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 7, 190, 30)];
self.nameTextField.enabled = NO;
[cell.contentView addSubview:self.nameTextField];
} else if (indexPath.row == 1) {
self.emailTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 7, 190, 30)];
[cell.contentView addSubview:self.emailTextField];
[self.emailTextField setReturnKeyType:UIReturnKeyDone];
[self.emailTextField setKeyboardType:UIKeyboardTypeEmailAddress];
} else if (indexPath.row == 2) {
self.genderSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.genderSwitch];
}
}
}
if (indexPath.section == 0) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [accountArray objectAtIndex:indexPath.row];
} else if (indexPath.section == 1) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [notArray objectAtIndex:indexPath.row];
} else if (indexPath.section == 2) {
self.cellName.text = [policyArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else if (indexPath.section == 3) {
self.cellName.text = [buttonsArray objectAtIndex:indexPath.row];
self.cellName.textAlignment = NSTextAlignmentCenter;
}
return cell;
}
Please try the following:
create a subclass of UITableViewCell with public properties (label, textfield). If you have different requirement for cells in different sections, maybe you should have different cell subclasses.
register these cell classes with the tableview in your view did load. e.g.
[self.tableView registerClass:[MySectionOneTableViewCell class] forCellReuseIdentifier:MySectionOneIdentifier];
[self.tableView registerClass:[MySectionTwoTableViewCell class] forCellReuseIdentifier:MySectionTwoIdentifier];
in the method below, just dequeue the cell after making a check for the section and set the properties.
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath )indexPath {
UITableViewCell cell;
if (indexPath.section == 0){
cell = (MySectionOneTableViewCell*)[tableView dequeueReusableCellWithIdentifier:MySectionOneIdentifier forIndexPath:indexPath;
cell.textLabel = #"foo";
}
return cell;
}
implement method, prepare for reuse in your custom uitableviewcell classes where you initialize all your labels and text fields. This method prepares the views of the cell for reuse.
e.g.
(void)prepareForReuse {
self.textLabel.text = #"";
}
As mentionned #rmaddy, you shouldn't mention the cell generation in your (!cell). The "code illustration" is the following:
- (void)viewDidLoad {
// This part wasn't included in any specific if/else condition dealing with cell properties (like section or row), not either being modified during the cell generation
self.emailTextField.delegate = self;
self.cellName = [[UILabel alloc] initWithFrame:CGRectMake(20, 12, 42, 20)];
self.cellName.textColor = [UIColor colorWithRed:0.137 green:0.145 blue:0.157 alpha:1];
self.cellName.font = [UIFont fontWithName:#"HelveticaNeue" size:14];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
// This part ensure you will initiate each cell with the correct identifier
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
cell.backgroundColor = [UIColor colorWithRed:0.953 green:0.953 blue:0.965 alpha:1] ;
}
[cell.contentView addSubview:self.cellName];
// You should check your code and commute the common condition together
if (indexPath.section == 0) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [accountArray objectAtIndex:indexPath.row];
// Be aware that your first section will contain only 3 rows
if (indexPath.row == 0) {
self.nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 7, 190, 30)];
self.nameTextField.enabled = NO;
[cell.contentView addSubview:self.nameTextField];
} else if (indexPath.row == 1) {
self.emailTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 7, 190, 30)];
[cell.contentView addSubview:self.emailTextField];
[self.emailTextField setReturnKeyType:UIReturnKeyDone];
[self.emailTextField setKeyboardType:UIKeyboardTypeEmailAddress];
} else if (indexPath.row == 2) {
self.genderSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.genderSwitch];
}
} else if (indexPath.section == 1) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
self.cellName.text = [notArray objectAtIndex:indexPath.row];
// Be aware that your second section will contain only 3 rows
if (indexPath.row == 0) {
self.acceptanceSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.acceptanceSwitch];
} else if (indexPath.row == 1) {
self.messageSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.messageSwitch];
} else if (indexPath.row == 2) {
self.likeSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(251, 6, 31, 51)];
[cell.contentView addSubview:self.likeSwitch];
}
} else if (indexPath.section == 2) {
// Here you are not adding any specific content to your section 2
self.cellName.text = [policyArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else if (indexPath.section == 3) {
// The same, your fourth section won't content any specific content
// You should add something like [cell addSubview:MyCustomView]
self.cellName.text = [buttonsArray objectAtIndex:indexPath.row];
self.cellName.textAlignment = NSTextAlignmentCenter;
}
return cell;
}
As I mentioned in my comments, if your local properties (cellName, nameTextField, genderSwitch, etc...) are well implemented, you will have only 6 row in all your table (3 in the first section and 3 in the second. Your third and fourth section will be empty since you didn't mention any subview within them.
Finally, since your code contained many confusion for me, it is possible I made some mistake in my rewriting, so feel free to correct me in this case.
Hopping it will help you in your work.
I have made a form by code to sign up within the application but if I scroll up and down the cells which are not visible get overridden with the setup of other cells... Has anyone experienced something like that? I'm pretty sure that I'm missing out on some configuration but I don't know which.
Here is my code.
Its a lot of code....sorry. But I really don't know where to start
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return 4;
} else if (section == 1) {
return 4;
} else {
return 5;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return #"Perönliche Informationen";
} else if (section == 1) {
return #"Anschrift";
} else {
return #"myClassico Profil";
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath section] == 0) {
if ([indexPath row] == 3) {
return 210;
} else {
return 44;
}
}
else if ([indexPath section] == 1) {
if ([indexPath row] == 0) {
return 80;
} else if ([indexPath row] == 3) {
return 210;
} else {
return 44;
}
}
else if ([indexPath section] == 2) {
return 44;
}
else {
return 44;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"anmeldenCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([indexPath section] == 0) {
if ([indexPath row] == 0) {
UISegmentedControl *gender = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Frau", #"Herr", nil]];
gender.frame = CGRectMake(99, 8, 124, 28);
gender.selectedSegmentIndex = 0;
[cell.contentView addSubview:gender];
} else if ([indexPath row] == 1) {
UITextField *vorname = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 300, 44)];
vorname.placeholder = #"Vorname";
[cell.contentView addSubview:vorname];
} else if ([indexPath row] == 2) {
UITextField *nachname = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 300, 44)];
nachname.placeholder = #"Nachname";
[cell.contentView addSubview:nachname];
} else {
//Code below is backup code in case someone really dislikes the UIDatePicker. Code is fully functional.
/*
UITextField *gebTag = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 80, 44)];
UITextField *gebMonat = [[UITextField alloc] initWithFrame:CGRectMake(108, 0, 100, 44)];
UITextField *gebJahr = [[UITextField alloc] initWithFrame:CGRectMake(216, 0, 100, 44)];
gebTag.placeholder = #"TT";
gebMonat.placeholder = #"MM";
gebJahr.placeholder = #"JJ";
[cell.contentView addSubview:gebTag];
[cell.contentView addSubview:gebMonat];
[cell.contentView addSubview:gebJahr];*/
UILabel *gebLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 280, 50)];
gebLabel.text = #"Geburtsdatum";
UIDatePicker *gender = [[UIDatePicker alloc] initWithFrame:CGRectMake(20, 30, 320, 180)];
[cell.contentView addSubview:gender];
[cell.contentView addSubview:gebLabel];
} //ENDE SECTION 1 (INFORMATIONEN ZUR PERSON)
} else if ([indexPath section] == 1) {
if ([indexPath row] == 0) {
UITextField *adresseStrasse = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
adresseStrasse.placeholder = #"Straße";
UITextField *adresseHNR = [[UITextField alloc] initWithFrame:CGRectMake(180, 30, 120, 44)];
adresseHNR.textAlignment = 2;
adresseHNR.placeholder = #"Hausnummer";
[cell.contentView addSubview:adresseStrasse];
[cell.contentView addSubview:adresseHNR];
} else if ([indexPath row] == 1) {
UITextField *adresseZusatz = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
adresseZusatz.placeholder = #"Adresszusatz (optional)";
[cell.contentView addSubview:adresseZusatz];
} else if ([indexPath row] == 2) {
UITextField *adressePLZ = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 100, 44)];
adressePLZ.placeholder = #"PLZ";
UITextField *adresseOrt = [[UITextField alloc] initWithFrame:CGRectMake(110, 0, 170, 44)];
adresseOrt.placeholder = #"Ort";
[cell.contentView addSubview:adressePLZ];
[cell.contentView addSubview:adresseOrt];
} else {
UILabel *land = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 150, 20)];
land.text = #"Land";
länderPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(20, 20, 300, 180)];
[länderPicker setDelegate:self];
array = [[NSMutableArray alloc] init];
[array addObject:#"Deutschland"];
[array addObject:#"Österreich"];
[array addObject:#"Schweiz"];
[cell.contentView addSubview:land];
[cell.contentView addSubview:länderPicker];
} //ENDE SECTION 2 (ADRESSEN INFORMATIONEN)
} else if ([indexPath section] == 2){
if ([indexPath row] == 0) {
UITextField *email = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
email.placeholder = #"E-Mail";
[cell.contentView addSubview:email];
} else if ([indexPath row] == 1) {
UITextField *telefon = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
telefon.placeholder = #"Telefon";
[cell.contentView addSubview:telefon];
} else if ([indexPath row] == 2) {
UITextField *mtelefon = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
mtelefon.placeholder = #"Mobiltelefon (optional)";
[cell.contentView addSubview:mtelefon];
} else if (indexPath.row == 3) {
UITextField *passwort = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
passwort.placeholder = #"Passwort";
[cell.contentView addSubview:passwort];
} else {
UITextField *passwortWiederholung = [[UITextField alloc] initWithFrame:CGRectMake(20, 0, 280, 44)];
passwortWiederholung.placeholder = #"Passwort wiederholen";
[cell.contentView addSubview:passwortWiederholung];
} //ENDE SECTION 3 (MYCLASSICO ACCOUNT INFORMATIONEN)
}
return cell;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [array count];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [array objectAtIndex:row];
}
Use different identifier for cells:
static NSString *CellIdentifier = #"anmeldenCell";
or prepare reset function for them.
Your problem is that cells are reused between sections. You are adding subview here [cell.contentView addSubview:gender]; and you never remove it - so it will be added several times to the same cell + the cell with this view will be used in other sections as well.
Best approach will be to prepare custom cell per section and use different CellIdentifier for them. Also when you reuse them assing a view to it's properly instead of adding subview several times.
BTW. use enumerations for sections to increase readability, instead of 1,2,3,4 use kSectionMyProfile, etc...
Rookie ios question. I am trying to create a sign up form using a table view controller. I am trying add textfields to each cell programmatically in the cellForRowAtIndexPath method but all my text fields seem to getting created on the first cell - one overlapping the other. Here is my code.
Here is how my cells are rendering. I think I am doing something goofy with the part that is reusing the cells. I did check some some other similar threads on stackoverflow but none of them helped. Could you please tell me what i am missing or is this even the way this is supposed to be done. Your inputs are really appreciated.
Thanks,
Mike
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"signUpFields" forIndexPath:indexPath];
// Configure the cell...
if (indexPath.row == 0){
//self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.firstName.placeholder = #"First Name";
self.firstName.autocorrectionType = UITextAutocorrectionTypeNo;
[self.firstName setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.firstName;
[cell.contentView addSubview:self.firstName];
}
if (indexPath.row == 1){
self.lastName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.lastName.placeholder = #"Last Name";
self.lastName.autocorrectionType = UITextAutocorrectionTypeNo;
[self.lastName setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.lastName;
[cell.contentView addSubview:self.lastName];
}
if (indexPath.row == 2){
self.emailId = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.emailId.placeholder = #"Email Id";
self.emailId.autocorrectionType = UITextAutocorrectionTypeNo;
[self.emailId setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.emailId;
[cell.contentView addSubview:self.emailId];
}
if (indexPath.row == 3){
self.password = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.password.placeholder = #"Password";
self.password.secureTextEntry = YES;
self.password.autocorrectionType = UITextAutocorrectionTypeNo;
[self.password setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.password;
[cell.contentView addSubview:self.password];
}
self.firstName.delegate = self;
self.lastName.delegate = self;
self.emailId.delegate = self;
self.password.delegate = self;
[self.signUpTable addSubview:self.firstName];
[self.signUpTable addSubview:self.lastName];
[self.signUpTable addSubview:self.emailId];
[self.signUpTable addSubview:self.password];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Try this..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (indexPath.row == 0){
//self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.firstName.placeholder = #"First Name";
self.firstName.autocorrectionType = UITextAutocorrectionTypeNo;
[self.firstName setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.firstName;
[cell addSubview:self.firstName];
}
if (indexPath.row == 1){
self.lastName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.lastName.placeholder = #"Last Name";
self.lastName.autocorrectionType = UITextAutocorrectionTypeNo;
[self.lastName setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.lastName;
[cell addSubview:self.lastName];
}
if (indexPath.row == 2){
self.emailId = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.emailId.placeholder = #"Email Id";
self.emailId.autocorrectionType = UITextAutocorrectionTypeNo;
[self.emailId setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.emailId;
[cell addSubview:self.emailId];
}
if (indexPath.row == 3){
self.password = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.password.placeholder = #"Password";
self.password.secureTextEntry = YES;
self.password.autocorrectionType = UITextAutocorrectionTypeNo;
[self.password setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.password;
[cell addSubview:self.password];
}
self.firstName.delegate = self;
self.lastName.delegate = self;
self.emailId.delegate = self;
self.password.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
no need to add again text view in table view, this is wrong. Try this, this will work for you but better you should create a custom Cell and use. That is the best way to do it, because you can use whatever you want with Cell.
Don't add them as subviews, set them as the cell's accessory view.
- (UITextField*)getTextField{
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 20, 35)];
tf.delegate = self;
tf.textColor = [UIColor colorWithRed:.231 green:.337 blue:.533 alpha:1];
tf.autocorrectionType = UITextAutocorrectionTypeNo;
tf.borderStyle = UITextBorderStyleNone;
tf.frame = CGRectMake(0, 20, 170, 30);
tf.clearButtonMode = UITextFieldViewModeWhileEditing;
tf.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
tf.font = [UIFont systemFontOfSize:13];
return tf;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.textLabel.font = [UIFont systemFontOfSize:13];
cell.detailTextLabel.font = [UIFont systemFontOfSize:13];
cell.detailTextLabel.numberOfLines = 2;
}
if (indexPath.section == 0) {
UITextField *tf = (UITextField*)cell.accessoryView;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.numberOfLines = 2;
tf = [self getTextField];
cell.accessoryView = cell.editingAccessoryView = tf;
[((UITextField*)cell.accessoryView) setBorderStyle:self.tableView.editing ? UITextBorderStyleRoundedRect : UITextBorderStyleNone];
[((UITextField*)cell.accessoryView) setUserInteractionEnabled:self.tableView.editing ? YES : NO];
[((UITextField*)cell.accessoryView) setTextAlignment:!self.tableView.editing ? UITextAlignmentRight : UITextAlignmentLeft];
((UITextField*)cell.accessoryView).tag = indexPath.row;
}
return cell;
}
The idea is that the cell is re-drawn each time it appears on screen, coming from off the screen and if you add the text field with addSubview:, it will add it each time as well. You COULD do it, but then you have to clear the cell's contentView of subviews, but that requires extra work, cpu and memory use, and not to say it's the least elegant solution.
Looks like you have just four cells you want to display. This is a static case, the cells don't change, you should create this tableView and its cells statically in the xib/storyboard. That is the preferred way here.
If you really want to do it programmatically, create four UITableViewCells with the behavior you want before hand. Keep them in an array. Inside cellForRowAtIndex path return cellArray[indexPath.row];
Note this is the best approach only because you have just four tableViewCells.
ReuseIdentifiers come in handy only if you have more cells than can be accommodated on the screen at once. So in your case, you never actually reuse the cells.
keep this one and try it,
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *MyIdentifier = [NSString stringWithFormat:#"%d%d",indexPath.row,indexPath.section];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
//your stuff.
}
}
Try to use this one ...And there is no need to add these textfield to tableview. So please remove some code..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"signUpFields" forIndexPath:indexPath];
// Configure the cell...
if (indexPath.row == 0){
//self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.firstName.placeholder = #"First Name";
self.firstName.autocorrectionType = UITextAutocorrectionTypeNo;
[self.firstName setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.firstName;
[cell addSubview:self.firstName];
}
if (indexPath.row == 1){
self.lastName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.lastName.placeholder = #"Last Name";
self.lastName.autocorrectionType = UITextAutocorrectionTypeNo;
[self.lastName setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.lastName;
[cell addSubview:self.lastName];
}
if (indexPath.row == 2){
self.emailId = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.emailId.placeholder = #"Email Id";
self.emailId.autocorrectionType = UITextAutocorrectionTypeNo;
[self.emailId setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.emailId;
[cell addSubview:self.emailId];
}
if (indexPath.row == 3){
self.password = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
self.password.placeholder = #"Password";
self.password.secureTextEntry = YES;
self.password.autocorrectionType = UITextAutocorrectionTypeNo;
[self.password setClearButtonMode:UITextFieldViewModeWhileEditing];
//cell.accessoryView = self.password;
[cell addSubview:self.password];
}
self.firstName.delegate = self;
self.lastName.delegate = self;
self.emailId.delegate = self;
self.password.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Instead of writing more cells just create one custom cell with textfield.Give the tag for each textfield and also set the count of rows in numberOfRowsIntheSections then it will display the cells how much you need. I think it will helps you.
Before You follow my Answer i wnat to tell you that following code is bad for memory management because it will create new cell for each rows of UITableView, so be careful for it.
But it is better to use, When UITableView Have Limited rows (about 50-100 may be ) then following code is helpful in your case, use it, If it is suitable for you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
/// Put/Create your UITextField or any Controls here
}
return cell;
}
#Mike : First of all I will suggest you to go with StoryBoard or Nib files.
If you use this, then you can use following code
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField = (UITextField *)[cell viewWithTag:1];
txtField.text = #"Latest";
return cell;
}
Based on row number you can set text.
If you want to add the UITextField at run time. then you can use following code.
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField = [[UITextField alloc] initWithFrame:CGRectMake(165.0, 7.0, 150.0, 30.0)];
txtField.text = #"Latest";
[cell.contentView addSubview:txtField];
return cell;
}
You can assign different tag and based on tags you can store those values.
When I scroll my tableview, the text gets all mashed up from the cells below. It's probably cause I recreate the UILabels every time cellForRow gets loaded, but I wouldn't know how to fix it:
(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = [indexPath row];
NSDictionary *currentRowDictionary = nil;
if (tableView == [[self searchDisplayController] searchResultsTableView])
currentRowDictionary = [[self searchResults] objectAtIndex:row];
else
currentRowDictionary = [[self tableData] objectAtIndex:row];
NSString *voornaam = [currentRowDictionary objectForKey:#"voornaam"];
NSString *achternaam = [currentRowDictionary objectForKey:#"achternaam"];
NSString *tussenvoegsel = [currentRowDictionary objectForKey:#"tussenvoegsel"];
voornaamLbl = [[[UILabel alloc] initWithFrame:CGRectMake(5, 10, 300, 40)] autorelease];
voornaamLbl.font = [UIFont fontWithName:#"TrebuchetMS-Bold" size:19];
voornaamLbl.text = voornaam;
voornaamLbl.numberOfLines = 0;
[voornaamLbl sizeToFit];
tussenvoegselLbl = [[[UILabel alloc] initWithFrame:CGRectMake(voornaamLbl.frame.size.width + 10, 10, 300, 40)] autorelease];
tussenvoegselLbl.text = tussenvoegsel;
tussenvoegselLbl.numberOfLines = 0;
[tussenvoegselLbl sizeToFit];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[cell.contentView addSubview:voornaamLbl];
if ([tussenvoegsel length] != 0)
{
[cell.contentView addSubview:tussenvoegselLbl];
achternaamLbl = [[[UILabel alloc] initWithFrame:CGRectMake(voornaamLbl.frame.size.width +
tussenvoegselLbl.frame.size.width + 15, 10, 300, 40)] autorelease];
} else {
achternaamLbl = [[[UILabel alloc] initWithFrame:CGRectMake(voornaamLbl.frame.size.width + 10, 10, 300, 40)] autorelease];
}
achternaamLbl.text = achternaam;
achternaamLbl.numberOfLines = 0;
[achternaamLbl sizeToFit];
[cell.contentView addSubview:achternaamLbl];
return cell;
}
You alloc and init new labels for everytime a cell is used. Cells are reused during scroll so your multiplying labels each time.
The best way is to create a seperate UITableViewCell subclass that creates the label on load, then in cellForRowAtIndexPath you use your new cell subclass and set the labels text
The end of this tutorial can help with cell subclasses http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1
In my UITableView I am trying to display all the items in my plist but its not showing all the items. Actually it is showing most of it but the lower items are being repeated for some odd reason. I basically want to show all the keys in the plist with their respective values. Is the list too long to display? there's about 30 items.
First I tried to sort the keys and thought that was the problem, so then I didn't sort at all and I get the same problem, lower down the list the items get repeated and not showing the last 3 items. Is there a limit?
Below is some code, I've just modified to fit:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"PreferencesCell1";
static NSString *CellIdentifier2 = #"PreferencesCell2";
static NSString *CellIdentifier3 = #"PreferencesCell3";
UITableViewCell *cell;
NSArray *keys = [[[preferences objectAtIndex:indexPath.section] objectForKey:#"Rows"] allKeys];
NSString *prefName = [keys objectAtIndex:indexPath.row];
if (indexPath.section == 0 || indexPath.section == 2) {
if(indexPath.section == 0)
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
else if(indexPath.section == 2)
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
if(indexPath.section == 0)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
else if(indexPath.section == 2)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
CGRect labelRect = CGRectMake(10, 5, 300, 31);
UILabel *settingName = [[UILabel alloc] initWithFrame:labelRect];
settingName.font = [UIFont boldSystemFontOfSize:17.0];
settingName.backgroundColor = [UIColor clearColor];
settingName.text = prefName;
[cell.contentView addSubview: settingName];
[settingName release];
}
} else if(indexPath.section == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier3];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier3] autorelease];
CGRect labelRect = CGRectMake(10, 5, 300, 31);
UILabel *label = [[UILabel alloc] initWithFrame:labelRect];
label.font = [UIFont boldSystemFontOfSize:17.0];
label.backgroundColor = [UIColor clearColor];
label.text = prefName;
[cell.contentView addSubview: label];
}
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
What I've found is that if I don't use the labels and just go for the generic cell.textLabel.text approach then all the items are displayed correctly. However if I use the UILabel approach, the bottom items are not shown. I need to go this route as I'm adding other items in the Cell.
Working Code.
Initialization and creation of cell must be created first, then using that referenced cell remove from superview, then render the subviews. So reordering of the code from above.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"PreferencesCell1";
static NSString *CellIdentifier2 = #"PreferencesCell2";
static NSString *CellIdentifier3 = #"PreferencesCell3";
UITableViewCell *cell;
NSArray *keys = [[[preferences objectAtIndex:indexPath.section] objectForKey:#"Rows"] allKeys];
NSString *prefName = [keys objectAtIndex:indexPath.row];
// Create/Initialize Cell first
if (indexPath.section == 0 || indexPath.section == 2) {
if(indexPath.section == 0)
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
else if(indexPath.section == 2)
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
if(indexPath.section == 0)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease];
else if(indexPath.section == 2)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2] autorelease];
}
} else if(indexPath.section == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier3];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier3] autorelease];
}
}
// remove from superview
[cell.contentView.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
// render the subviews
if (indexPath.section == 0 || indexPath.section == 2) {
cell.accessoryType = UITableViewCellAccessoryNone;
CGRect labelRect = CGRectMake(10, 5, 300, 31);
UILabel *settingName = [[UILabel alloc] initWithFrame:labelRect];
settingName.font = [UIFont boldSystemFontOfSize:17.0];
settingName.backgroundColor = [UIColor clearColor];
settingName.text = prefName;
[cell.contentView addSubview: settingName];
[settingName release];
} else if(indexPath.section == 1) {
CGRect labelRect = CGRectMake(10, 5, 300, 31);
UILabel *label = [[UILabel alloc] initWithFrame:labelRect];
label.font = [UIFont boldSystemFontOfSize:17.0];
label.backgroundColor = [UIColor clearColor];
label.text = prefName;
[cell.contentView addSubview: label];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
return cell;
}
It looks like cells are being reused and you are just adding new views to their existing contents. You need to reset the content, as described here: UITbleViewCell Class Reference. If you were just setting the cell's textLabel each time, setting a new value would suffice here, but if you are adding subviews you may need something more like [cell.contentView.subviews makeObjectsPerformSelector: #selector(removeFromSuperview)];
The Limit for a Tableview is the free RAM size.
Please post some Code. But i think that this could be a Problem with Cell caching.