I have implemented a viewController that contains a tableView which display user's data(firstName , lastName , birthday..) fetched from login Facebook or twitter or google Plus .I have made three custom cells : firstNameTableViewCell , lastNameTableViewCell,birthdayTableViewCell : All of this three cells contains a label ans a textfield.I want that when the user touch the corresponding cell , he will be able to change his data.
Technically , I have used the tableView's delegate methods : cellForRowAtIndexPath & didSelectRowAtIndexPath but I don't have what I want : When I open the interface : the label is disappering and when i touch the corresponding cell , nothing that changes .
This my code :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row)
{
case 0 : {
NSString *cellIdentifier = [[NSString alloc] initWithFormat:#"genderCell"];
genderTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[self.tableUserData objectAtIndex:indexPath.row]];
cell.maleImageView = [cell showGender:self.gender];
cell.femaleImageView =[cell showGender:self.gender];
return cell ;
break;
}
case 1 : {
NSString *cellIdentifier = [[NSString alloc] initWithFormat:#"firstNameCell"];
firstNameTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[self.tableUserData objectAtIndex:indexPath.row]];
cell.firstNameLabel.text = [NSString stringWithFormat:#"%#",self.firstName];
cell.firstNameTextField.hidden =YES ;
return cell;
break;
}
case 2 : {
NSString *cellIdentifier = [[NSString alloc] initWithFormat:#"lastNameCell"];
lastNameTableViewCell *cell= [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[self.tableUserData objectAtIndex:indexPath.row]];
cell.lastNameLabel.text = [NSString stringWithFormat:#"%#",self.lastName];
cell.lastNameTextField.hidden = YES ;
return cell;
break;
}
case 3 : {
NSString *cellIdentifier = [[NSString alloc] initWithFormat:#"BirthDayCell"];
birthDayTableViewCell *cell= [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[self.tableUserData objectAtIndex:indexPath.row]];
cell.birthDaylabel.text = [NSString stringWithFormat:#"%#",self.birthDay];
cell.birthDayTextField.hidden = YES ;
return cell;
break;
}
case 4 : {
NSString *cellIdentifier = [[NSString alloc] initWithFormat:#"heightCell"];
heightTableViewCell *cell= [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[self.tableUserData objectAtIndex:indexPath.row]];
cell.heightUnityLabel.text = [NSString stringWithFormat:#"%#",self.heightUnity];
self.height = [cell.heightTextField.text floatValue];
return cell;
break;
}
case 5 : {
NSString *cellIdentifier = [[NSString alloc] initWithFormat:#"weightCell"];
weightTableViewCell *cell= [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.textLabel.text = [NSString stringWithFormat:#"%#",[self.tableUserData objectAtIndex:indexPath.row]];
cell.weightUnityLabel.text = [NSString stringWithFormat:#"%#",self.weightUnity];
self.weight = [cell.weightTextField.text floatValue];
return cell;
break;
}
default:
break ;
}
return nil ;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"%ld",indexPath.row);
if (indexPath.row == 1) {
firstNameTableViewCell *cell = [firstNameTableViewCell new];
cell.firstNameLabel.hidden = YES ;
cell.firstNameTextField.hidden = NO ;
cell.firstNameTextField.text = cell.firstNameLabel.text ;
[self.userDataTableView reloadData];
}
else if (indexPath.row == 2) {
lastNameTableViewCell *cell = [lastNameTableViewCell new];
cell.lastNameLabel.hidden = YES ;
cell.lastNameTextField.hidden = NO ;
cell.lastNameTextField.text = cell.lastNameLabel.text ;
[self.userDataTableView reloadData];
}
else if (indexPath.row == 3) {
birthDayTableViewCell *cell = [birthDayTableViewCell new];
cell.birthDaylabel.hidden = YES ;
cell.birthDayTextField.hidden = NO ;
cell.birthDayTextField.text = cell.birthDaylabel.text ;
[self.userDataTableView reloadData];
}
}
Inside:
-(void)tableView:tableView didSelectRowAtIndexPath:indexPath
It is much better if you'll just use the indexPath to return the cell like:
firstNameTableViewCell *cell = (firstNameTableViewCell *)[tableView cellForRowAtIndexPath:(NSIndexPath)];
..
cell.firstNameTextField.hidden = NO ;
cell.firstNameTextField.text = cell.firstNameLabel.text;
// but do not reload the table yet..
Instead make cell.firstNameTextField as the first responder and let the user enter necessary data..
[cell.firstNameTextField becomeFirstResponder];
if the user is done editing and you have database for that, update your database on DONE, then your table dataSource (self.tableUserData), only then you need the [self.userDataTableView reloadData];, and i think you dont really want to reload the whole table for that single edit,[self.userDataTableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:(UITableViewRowAnimation)] reloading only the target indexPath is much more suitable for that..
-reloadData means 'reloading everything in the table based from your array data source'. meaning settings of values made inside:
-(void)tableView:tableView willDisplayingCell:cell forRowAtIndexPath:indexPath
and
-(UITableViewCell *)tableView:tableView cellForRowAtIndexPath:indexPath
ex:
cell.firstNameLabel.text = [NSString stringWithFormat:#"%#",self.firstName];
cell.lastNameTextField.hidden = YES ;
will be refreshed and set as is...
Edit
Also i've noticed that you didn't allocate your cells if nil after dequeueReusableCellWithIdentifier(i wonder why your app is not crashing because of it), anyway it is good for the memory to reuseCells like:
firstNameTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[firstNameTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
Related
I have an array of names that I'm showing via tableview. You can select up to a total of 3 names, and you cannot re-select the same names. To do this I implemented the following code in cellForRowAtIndexPath:. When I run the code the names come up fine, but there are multiple red cells with names that I did not select.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *sectionTitle = [nameSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionNames = [names objectForKey:sectionTitle];
NSString *name = [sectionNames objectAtIndex:indexPath.row];
cell.textLabel.text = name;
if ([name isEqualToString: self.name1] || [name isEqualToString: self.name2] || [name isEqualToString: self.name3]) {
[cell setUserInteractionEnabled:NO];
cell.backgroundColor = [UIColor redColor];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Reading a similar problem here, they were saying that it's because the cells are being reused - but if this were true, how is the tableview still displaying the correct names in the correct position?
I tried to simplify the code into this, and still to no avail, there were multiple red cells.
myIP = [NSIndexPath indexPathForRow:0 inSection:0];
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TableCell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *sectionTitle = [nameSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionNames = [names objectForKey:sectionTitle];
NSString *name = [sectionNames objectAtIndex:indexPath.row];
cell.textLabel.text = name;
if (indexPath == myIP) {
cell.backgroundColor = [UIColor redColor];
}
return cell;
}
I can post a screenshot if needed. Note: The intended names were correctly labeled with red.
The issue is happening due to cell re-using. When a cell with red background is re-used it'll still be in red background, you are not re-setting it anywhere in your code. You need to put a else case to your if condition used in cellForRowAtIndexPath: method.
if ([name isEqualToString: self.name1] || [name isEqualToString: self.name2] || [name isEqualToString: self.name3])
{
[cell setUserInteractionEnabled:NO];
cell.backgroundColor = [UIColor redColor];
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
[cell setUserInteractionEnabled:YES];
cell.backgroundColor = [UIColor clearColor];
// Other stuffs
}
I have a few custom cells that I would like to display information on. I made 2 new cells however it is only returning one cell. The top most cell's identifier is "Cell" and the bottom one is "quantityCell". I would like the product description to be on the top cell and the quantity on the bottom cell. The output I am getting now is only the quantity cell showing, but not the product cell. If I remove the quantity cell, the product cell will show. How should I go about doing this?
Thank you
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *quantityCellIdentifier = #"quantityCell";
UITableViewCell *quantityCell = [tableView dequeueReusableCellWithIdentifier:quantityCellIdentifier forIndexPath:indexPath];
DisplayInventoryTableViewController *inventoryItem = [[DisplayInventoryTableViewController alloc]init];
self.productName = [inventoryItem getProductTitle];
productTitle = self.productName;
cell.detailTextLabel.text = productTitle;
NSLog(#"productTitle %#", self.productName);
cell.textLabel.text = #"Product Title";
self.productQuantity = [inventoryItem getQuantity];
quantityCell.textLabel.text = #"Quantity";
quantityCell.detailTextLabel.text = self.productQuantity;
/*
// Configure the cell...
// cell.textLabel.text = productTitle;
cell.textLabel.text = #"Product Name";
cell.detailTextLabel.text = productTitle;
*/
return cell;return quantityCell;
}
Problem
The you can't return 2 parameters in the same time on a method. So where you say:
return cell;return quantityCell;
Only cell is being returned, the method ends on the first return.
Solution
You need to make logic which one time returns topCell and the other time bottomCell
So in your case you just need to have indexPath.row modulus 2, which can take any value and returns only 0 on even numbers and 1 on odd numbers.
So your code should be like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"";
if (indexPath.row%2==0) {
//Get the top cell
CellIdentifier = #"Cell";
} else {
//Get bottom cell
CellIdentifier = #"quantityCell";
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
DisplayInventoryTableViewController *inventoryItem = [[DisplayInventoryTableViewController alloc]init];
if (indexPath.row%2==0) {
//Customize topCell
self.productName = [inventoryItem getProductTitle];
productTitle = self.productName;
cell.detailTextLabel.text = productTitle;
NSLog(#"productTitle %#", self.productName);
cell.textLabel.text = #"Product Title";
} else {
//Customize bottom cell
self.productQuantity = [inventoryItem getQuantity];
cell.textLabel.text = #"Quantity";
cell.detailTextLabel.text = self.productQuantity;
}
return cell;
}
return cell;
return quantityCell;
The above 2 line you wrote in your function! After return statement the method stop executing further lines.
You could do something like this:
self.productName = [inventoryItem getProductTitle];
self.productQuantity = [inventoryItem getQuantity];
productTitle = self.productName;
if(indexPath.row == 0) {
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.detailTextLabel.text = productTitle;
cell.textLabel.text = #"Product Title";
return cell;
}
else {
NSString *quantityCellIdentifier = #"quantityCell";
UITableViewCell *quantityCell = [tableView dequeueReusableCellWithIdentifier:quantityCellIdentifier forIndexPath:indexPath];
quantityCell.textLabel.text = #"Quantity";
quantityCell.detailTextLabel.text = self.productQuantity;
return quantityCell;
}
Hope this helps.. :)
Thank you all, I ended up using a dictionary that returns all of the keys and values to the cells.
NSDictionary *inventoryDictionary = #{
#"Quantity" : productQuantity,
#"Price" : productPriceValue,
#"Product Title" : productTitle
};
NSLog(#"ProductStrings: %#", inventoryDictionary);
NSString *keys = [inventoryDictionary allKeys][indexPath.row];
NSString *providerNameString = keys;
cell.textLabel.text = providerNameString;
NSString *Values = [inventoryDictionary allValues][indexPath.row];
NSString *providerNameValue = Values;
cell.detailTextLabel.text = providerNameValue;
return cell;
How can i return the part of a string in a cell in Xcode?
I have a json responce:
{"Email":"john#appleseed.com","Password":"4321","lijst":"eieren, kaas, melk, 2 uien, brood(volkoren)"}
how can i get the value's at "lijst" in different cells in xcode?
So cell 1 = Eieren
cell 2 = Kaas
etc...
this is the code to display it all in one cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
switch (indexPath.row) {
case 0:
cell.textLabel.text = [self name];
cell.detailTextLabel.text = #"Name";
break;
case 1: {
NSString *email = [details objectForKey:#"Email"];
if (!email)
email = #"No email";
if ([email isKindOfClass:[NSArray class]])
email = #"<Multiple emails>";
cell.textLabel.text = email;
cell.detailTextLabel.text = #"Email";
break;
}
case 2:
cell.textLabel.text = self.details[#"lijst"];
cell.detailTextLabel.text = #"List";
break;
default:
break;
}
return cell;
}
It appears that you have parsed this JSON into a dictionary called self.details. You could then, as #bdesham pointed out, get an array of the individual values with componentsSeparatedByString:. For example, if you had a NSArray property called lijstArray, you could do something like:
NSString *lijstString = self.details[#"lijst"];
self.lijstArray = [lijstString componentsSeparatedByString:#", "];
Then, lijstArray[0] will have the first value, lijstArray[1] the second, etc. The number of values is [lijstArray count].
The above only works if you know that there will be exactly one and only one space after the commas. If you don't know that for sure, you'd just use #"," for the separator, but then trim the whitespace. For example, if you declared the lijstArray property to be a NSMutableArray, you could do something like:
NSString *lijstString = self.details[#"lijst"];
NSArray *tempArray = [lijstString componentsSeparatedByString:#","];
self.lijstArray = [NSMutableArray array];
for (NSString *lijstValue in tempArray) {
[self.lijstArray addObject:[lijstValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
Whichever approach you adopt, having populated an array, lijstArray, you can now use that in your cellForRowAtIndexPath. For example, let's assume your tableview had two sections, section 0 being the name and email, and section 1 being the individual lijstArray values, e.g.:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
return 2;
else if (section == 1)
return [self.lijstArray count];
return 0; // we never should get here, but in the spirit of defensive programming, let's make sure we handle this
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
if (indexPath.section == 0) {
switch (indexPath.row) {
case 0:
cell.textLabel.text = [self name];
cell.detailTextLabel.text = #"Name";
break;
case 1: {
NSString *email = [details objectForKey:#"Email"];
if (!email)
email = #"No email";
if ([email isKindOfClass:[NSArray class]])
email = #"<Multiple emails>";
cell.textLabel.text = email;
cell.detailTextLabel.text = #"Email";
break;
}
default:
break;
}
} else if (indexPath.section == 1) {
cell.textLabel.text = self.lijstArray[indexPath.row];
}
return cell;
}
Why the UITableViewCells don't reload the checkmarks after selecting, scrolling away, then scrolling back?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
#define CHECK_NULL_STRING(str) ([str isKindOfClass:[NSNull class]] || !str)?#"":str
static NSString *CellIdentifier = #"inviteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.textLabel.highlightedTextColor = [UIColor colorWithHexString:#"#669900"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.backgroundColor = [UIColor blackColor];
cell.textLabel.textColor = [UIColor whiteColor];
[[UITableViewCell appearance] setTintColor:[UIColor colorWithHexString:#"#669900"]];
if (cell == nil) {
cell = [[UITableViewCell alloc] init];
}
if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; }
BOOL isSearching = tableView != self.tableView;
NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects);
id p = arrayToUse[indexPath.row];
NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName));
NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName));
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)];
BOOL showCheckmark = [[stateArray objectAtIndex:indexPath.row] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSLog(#"It hit showCheckmark = YES, and stateArray is %#",stateArray[indexPath.row]);
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(#"It hit showCheckmark = NO, and stateArray is %#",stateArray[indexPath.row]);
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[stateArray insertObject:[NSNumber numberWithBool:YES] atIndex:indexPath.row];
[selectedObjects addObject:object];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[stateArray insertObject:[NSNumber numberWithBool:NO] atIndex:indexPath.row];
[selectedObjects removeObject:object];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You missed out the ! (inverse operator) on the following line meaning that the state will always be the same.
[stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:[[stateArray objectAtIndex:indexPath.row] boolValue]]];
It should be
[stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]];
Edit --- I've refactored both methods because it can be done with a lot less code and it will completely simplify the methods for you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"inviteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
BOOL isSearching = tableView != self.tableView;
NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects);
id p = arrayToUse[indexPath.row];
NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName));
NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName));
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)];
BOOL showCheckmark = [stateArray[indexPath.row] boolValue];
if (showCheckmark == YES) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedObjects addObject:object];
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedObjects removeObject:object];
}
stateArray[indexPath.row] = #(cell.accessoryType == UITableViewCellAccessoryCheckmark);
}
I suggest a more object oriented approach. This will ensure that your code is flexible and displays correctly all the time.
For each item you wish to display in your table, have a corresponding object. You mentioned that you are displaying contacts, so let's suppose your object is called "Contact":
//Contact.h
#interface Contact : NSObject
#property BOOL selected;
#property NSString *name;
#end
//Contact.m
#import Contact.h
#implementation Contact
+ (id) contactWithName:(NSString*)name {
Contact *nContact = [Contact new];
nContact.name = name;
nContact.selected = NO;
return nContact;
}
#end
Then, just make your view work something like this:
//ContactView.m
#interface ContactView()
#property NSMutableArray *contacts;
#end
#implementation ContactView
#synthesize contacts;
- (void) viewDidLoad {
[super viewDidLoad];
//get your contact list here. When creating contacts, be sure to assign their selected and their name as you require.
contacts = #[[Contact contactWithName:#"John"], [Contact contactWithName:#"Jane"]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = #"inviteCell";
UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
Contact *cellContact = [contacts objectAtIndex:indexPath.row];
cell.textLabel.text = cellContact.name;
cell.accessoryType = cellContact.selected == YES ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Contact *cellContact = [contacts objectAtIndex:indexPath.row];
cellContact.selected = !cellContact.selected;
[contacts replaceObjectAtIndex:indexPath.row withObject:cellContact];
[tableView reloadData]; //to refresh without animation
//[tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [tableView numberOfSections])] withRowAnimation:UITableViewRowAnimationTop]; //to refresh with animation
}
#end
And boom, easy to use tables that always look right, queue properly, and are object oriented for easy maintenance later.
The cell selection problem was not solved, even when insertObject was replaced with replaceWithObject, however, one should not waste time setting BOOL objects with an NSInteger inside an NSMutableArray. Instead, for cell selection memory, one should use NSDictionary like this:
#property (nonatomic, strong) NSMutableDictionary * selectedRowCollection;
- (void)viewDidLoad{
self.selectedRowCollection = [[NSMutableDictionary alloc] init];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
id object = contactsObjects[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedRowCollection setObject:#"1" forKey:[NSString stringWithFormat:#"%d",indexPath.row]];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedRowCollection removeObjectForKey:[NSString stringWithFormat:#"%d",indexPath.row]];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL showCheckmark = [[self.selectedRowCollection valueForKey:[NSString stringWithFormat:#"%d",indexPath.row]] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
You are not doing this UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
Allocating is necessary if cell is nil. Or it cause problem while scrolling.
I want to display in UITableView array like:
(
1,
{
date = 1351876762;
ncom = 0;
nid = 11739814;
"read_ncom" = 0;
text = "<div class=\"wikiText\"><!--4-->New note text </div>";
title = lol;
uid = 3795852;
}
)
Cells should have a label with "title" from this array.
How can I make that?
P.S.:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *textCell = [[array objectAtIndex:indexPath.row] objectForKey:#"title"];
cell.textLabel.text = textCell;
return cell;
}
returns signal SIGABRT.
Thanks.
[EDIT]
Your array seems to be weird. Try following and let me know the result.
NSString *textCell = [[array objectAtIndex:1] objectForKey:#"title"];
You should have cell with identifier "Cell" in your table (if you have storyboard) or create this cell manually
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[array objectAtIndex:1] objectforkey:#"title"];
try the above code
Replace this :
NSString *textCell = [[[array objectAtIndex:indexPath.row] objectForKey:#"1"]objectForKey:#"title"];