Row Order in UITableViewCell is wrong - objective-c

This is a simple class that extended UITableViewController, there's only one section total 5 rows. but when launch app, only show 2 record, when pressed the button, it will show more records with text field.
but, press simple button and press detail button , i found the order in table is wrong.
I don't know what happen, so can help me to solve this problem?
Many thanks
- (void)viewDidLoad
{
[super viewDidLoad];
tempSimpleAry = [#[#"simple1",#"simple2"] mutableCopy];
tempDetailAry = [#[#"detail A",#"detail B",#"detail C"] mutableCopy];
dataAry = [[NSMutableArray alloc]init];
[dataAry addObjectsFromArray:tempSimpleAry];
isExpanded = NO;
}
-(void)dealloc{
[super dealloc];
tempSimpleAry = nil;
tempDetailAry = nil;
dataAry = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (BOOL)textFieldShouldReturn:(UITextField *)aTextField {
[aTextField resignFirstResponder];
return YES;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return dataAry.count+1;
}
static NSString *BasicCellIdentifier = #"BasicCell";
static NSString *MyCellIdentifier = #"MyCell";
static NSString *LastCellIdentifier = #"LastCell";
UITableViewCell *Lastcell = nil;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = indexPath.row;
if(indexPath.row<tempSimpleAry.count){
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:BasicCellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [[NSString alloc]initWithFormat:#"%# %d", [dataAry objectAtIndex:row], row];
return cell;
}else if(indexPath.row < dataAry.count){
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyCellIdentifier forIndexPath:indexPath];
cell.myTitleLabel.text = [[NSString alloc]initWithFormat:#"%# %d", [dataAry objectAtIndex:row], row];
cell.myTextField.placeholder = [[NSString alloc]initWithFormat:#"%# %d", [dataAry objectAtIndex:row], row];
NSLog(#"MyTableViewCell - myTitlelabel = %#, mytextfield tag = %d, text = %#", cell.myTitleLabel.text, cell.myTextField.tag,cell.myTextField.text);
cell.myTextField.tag =100+indexPath.row;
return cell;
}else{
Lastcell = [tableView dequeueReusableCellWithIdentifier:#"LastCell" forIndexPath:indexPath];
Lastcell.textLabel.text = #"Detail";
return Lastcell;
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[currentEditingTextField resignFirstResponder];
NSMutableArray *tmpAry = [[NSMutableArray alloc]init];
if(indexPath.row == dataAry.count){
if(isExpanded){
int idx = dataAry.count-1;
for(int i=0; i<tempDetailAry.count;i++){
NSIndexPath *idxPaths = [NSIndexPath indexPathForRow:idx-i inSection:0] ;
[tmpAry addObject:idxPaths];
[dataAry removeLastObject];
}
[tableView deleteRowsAtIndexPaths:tmpAry withRowAnimation:UITableViewRowAnimationFade];
}else{
int idx = tempSimpleAry.count;
for(int i=0; i<tempDetailAry.count;i++){
NSIndexPath *idxPaths = [NSIndexPath indexPathForRow:idx+i inSection:0] ;
[tmpAry addObject:idxPaths];
[dataAry insertObject:[tempDetailAry objectAtIndex:i] atIndex:idx+i];
}
[tableView insertRowsAtIndexPaths:tmpAry withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView beginUpdates];
[self.tableView endUpdates];
isExpanded = !isExpanded;
if(!isExpanded)
Lastcell.textLabel.text = #"Detail";
else
Lastcell.textLabel.text = #"Simple";
}
}

It is because the cells are cached with cellIdentifier.
When you press Simple, you delete cells by the sequence, 'detail C 4', 'detail B 3', 'detail A 2'. So the 'detail C 4' cell is pushed into the cache queue first, then 'detail B 3' cell, finally 'detail C 2' cell.
Then you press Detail, the tableView query the cache queue one by one. Because the 'detail C 4' cell is at the front, it is popped first. So u use the cell with 'aa' in the textField, and then you set the cell.myTitleLabel.text and cell.myTextField.placeholder, but you don't set the cell.myTextField.text, which is 'aa'. Finally, the cell became 'detail A 2' with text 'aa' in the textField.
The same with the other two cells.
Is the above clear for you ?

It seems that u are only changing the textfield's place holder not its text, You should also save the textfield's text into an array and set it in cellForRowAtIndexPath!

Related

Why my tableView did not display anything

i want select over 50 in the first section,and others in the second section ,but there is no value display in tableView ,and when i use NSlog("%#",self.over50) ,there is no reaction
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell" ];
NSArray* items = [[BNRItemStore shareStore] allItems];
self.itemsUnder50 = [[NSMutableArray alloc] init];
self.itemsOver50 = [[NSMutableArray alloc] init];
for (BNRItem *item in items) {
if (indexPath.section ==0) {
[self.itemsOver50 addObject:item];
cell.textLabel.text = [self.itemsOver50[indexPath.row] description];
NSLog(#"%#",self.itemsUnder50);
}
else if(indexPath.section == 1){
[self.itemsUnder50 addObject:item];
cell.textLabel.text = [self.itemsUnder50[indexPath.row] description];
}
}
return cell;
}
connect the datasource and delegate of the tableview to the viewController

Accessory checkmarks disappear when scrolling Objective-C

I have a tableview that I can add and remove multiple checkmarks. The only issue is if I put 3 checkmarks and scroll away, when I return the checkmarks are gone. I can't find anywhere on the internet a solution that works, and I've tried several variation and still nothing.
This is my code in cellForRowAtIndex that should be holding the checkmarks in place.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseIdentifier = #"contactCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
NSDictionary *contact = [self.tableData objectAtIndex:indexPath.row];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1];
NSString *firstName = contact[#"firstName"];
nameLabel.text = [firstName stringByAppendingString:[NSString stringWithFormat:#" %#", contact[#"lastName"]]];
UILabel *phoneNumber = (UILabel *)[cell viewWithTag:2];
NSArray *phones = contact[#"phones"];
if ([phones count] > 0) {
NSDictionary *phoneItem = phones[0];
phoneNumber.text = phoneItem[#"value"];
}
UIImageView *cellIconView = (UIImageView *)[cell.contentView viewWithTag:888];
UIImage *image = contact[#"image"];
cellIconView.image = (image != nil) ? image : [UIImage imageNamed:#"smiley-face"];
cellIconView.contentScaleFactor = UIViewContentModeScaleAspectFill;
cellIconView.layer.cornerRadius = CGRectGetHeight(cellIconView.frame) / 2;
// Need to fix
if([checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Here is the didSelectRowAtIndexPath method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell* checkCell = [tableView cellForRowAtIndexPath:indexPath];
if(checkCell.accessoryType == UITableViewCellAccessoryCheckmark)
{
checkCell.accessoryType = UITableViewCellAccessoryNone;
NSMutableArray *i = [[NSMutableArray alloc] init];
for (NSIndexPath *indexPath in [self.tableView indexPathsForSelectedRows]) {
[i addObject:self.tableData[indexPath.row]];
// Go inside pull the numbers from the users and save in an NSArray
// NSArray *contacts = i;
// self.recipients = [[NSMutableArray alloc] init];
for (NSDictionary* dict in i) {
// Grab phones
NSDictionary *contactNumber = [dict objectForKey:#"phones"];
for (NSDictionary* dict2 in contactNumber) {
// Grabs the phone numbers
NSString* value = [dict2 objectForKey:#"value"];
int index = [self.recipients indexOfObject:value];
[self.recipients removeObjectAtIndex:index];
[self.selectedUsers removeObjectAtIndex:index];
NSLog(#"The number that has a checkmark%#", value);
NSLog(#"the array of all%#", self.recipients);
NSLog(#"At index %lu", (unsigned long)[self.recipients indexOfObject:value]);
// [_recipients addObject:value];
}
}
// NSLog(#"Phone Numbers: %#",_recipients);
}
}
else
{
[self getNumber];
NSLog(#"clicking %#", self.recipients);
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
checkedIndexPath = indexPath;
}
}
I found The Solution:
You must save each indexPath into an array(put this code in didSelectRowAtIndexPath) and then in cellForRowAtIndexPath add the following code
if([self.checkedCells containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
Also in the didSelectRowAtIndexPath
Make sure to delete the indexPath when deselecting the row.
if(checkCell.accessoryType == UITableViewCellAccessoryCheckmark) {
checkCell.accessoryType = UITableViewCellAccessoryNone;
[self.checkedCells removeObject:indexPath];
I hope this helps someone. I been wrestling with this all day.
Make checkedIndexPath a #property (nonatomic, strong) and use self.checkedIndexPath whenever you refer to it. You're losing the reference after didSelectRowAtIndexPath exits. Set a breakpoint in cellForRowAtIndexPath and look at checkedIndexPath, I bet it's nil.
Maybe you should check if the isEqual functionality does what you expect. You could make sure by trying:
if (_checkedIndexPath.section == indexPath.section &&
_checkedIndexPath.row == indexPath.row)
If you still do not get the expected result, perhaps log the values of section and row to see where it goes wrong.
Please note that if for some reason _checkedIndexPath is a weak variable or gets deallocated, this check will fail.
You could also check that your cells are properly dequeued before being modified and that you are returning the correct cells.
If you want to store more than one checked row, of course, you will need more than one indexPath variable (just one _checkedIndexPath will not do it).

Hide tableview sections on tap gesture of section header

I want to hide the NSArrays (menuItems, about, and charting) on the click for the specific section header for the tableview cell arrays. I got the section header to highlight and de-highlight depending on tap gesture recognizer count but I can not get the tableview cells to hide when that specific section header is clicked. Can someone please help? Thank you! Here is my .m code. My GCF float method is located at the bottom of the .m.
#interface SidebarTableViewController ()
#end
#implementation SidebarTableViewController {
NSArray *menuItems;
NSArray *about;
NSArray *charting;
}
- (void)viewDidLoad {
[super viewDidLoad];
menuItems = #[#"Home",#"Field Goal", #"Punt", #"Kick Off", #"Snapper", #"Punter"];
about = #[#"Home",#"About Us", #"Tutorial"];
charting = #[#"Home",#"Charting"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if (indexPath.section==0) {
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
else if(indexPath.section==1) {
NSString *CellIdentifier2 = [charting objectAtIndex:indexPath.row];
UITableViewCell *cell2 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2 forIndexPath:indexPath];
return cell2;
}
else {
NSString *CellIdentifier1 = [about objectAtIndex:indexPath.row];
UITableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1 forIndexPath:indexPath];
return cell1;
}
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Set the title of navigation bar by using the menu items
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3 ;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section==0)
{
return [menuItems count];
}
else if(section==1)
{
return [charting count];
}
else{
return [about count];
}
}
- (UIView*) tableView: (UITableView*) tableView viewForHeaderInSection: (NSInteger) section
{
UILabel *headerLabel = [[UILabel alloc]init];
headerLabel.tag = section;
headerLabel.userInteractionEnabled = YES;
headerLabel.backgroundColor = [UIColor grayColor];
if(section == 0){
headerLabel.text = [NSString stringWithFormat:#"Timers Without Charting"];
}
else if(section==1)
{
headerLabel.text = [NSString stringWithFormat:#"Charting with Timers"];
}
else{
headerLabel.text = [NSString stringWithFormat:#"About Us/Tutorial"];
}
headerLabel.frame = CGRectMake(0, 0, tableView.tableHeaderView.frame.size.width, tableView.tableHeaderView.frame.size.height);
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(catchHeaderGesture:)];
tapGesture.cancelsTouchesInView = NO;
[headerLabel addGestureRecognizer:tapGesture];
return headerLabel;
//return nil;
}
-(void)catchHeaderGesture:(UIGestureRecognizer*)sender
{
border ++;
if (border == 1)
{
UILabel *caughtLabel = (UILabel*)sender.view;
caughtLabel.layer.borderColor = [UIColor yellowColor].CGColor;
caughtLabel.layer.borderWidth = 2;
}
if (border == 2 )
{
UILabel *caughtLabel = (UILabel*)sender.view;
caughtLabel.layer.borderColor = [UIColor clearColor].CGColor;
caughtLabel.layer.borderWidth = 2;
border = 0;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
border ++;
if (border == 1)
{
UITableViewCell* cell = [menuItems objectAtIndex:indexPath.row];
cell.hidden = YES;
return 40.0;
}
if (border == 2 )
{ border = 0;
UITableViewCell* cell = [menuItems objectAtIndex:indexPath.row];
cell.hidden = YES;
}
return 0;
}
#end
You need a few couple things to make this work.
section headers that respond to taps.
a method for expanding or collapsing a section.
some way to track which sections are collapsed.
The first is trivial. Return a UIView for the header, and attach a UITapGestureRecognizer to it. You'll need a method to figure out which section it is. You can use the tag property, or you can store the views in an NSMutableArray.
In tableView:numberOfRowsInSection: you return 0 if the section is collapsed, or the actual number, if not.
In the handler for the gesture recognizer, you toggle the collapsed/expanded state, and then you call `[self.tableView reloadSections:withRowAnimation:] to update the visuals.
(I do see in your posted code that you already handle part of this.)

UITableViewController with multiple segues going to the wrong view

So I'm completely stumped here. I'm using xcode 5 and I have a table view with 2 segues. I tried to set the segues originally with two different prototype cells, but that didn't work. So I now have both segues set at the UITableViewController. It seems like whichever segue I created last is the one it goes to. I'm not getting any errors and when I step through the code, it fires on the correct line to execute the segue.
This seems to execute perfectly every time but it just doesn't go to the correct view.
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if([currentTableViewType isEqualToString:#"feedbackOnly"]){
// hits this line correctly
[self performSegueWithIdentifier:#"ShowSendFeedback" sender:indexPath];
} else {
// hits this line correctly
[self performSegueWithIdentifier:#"ShowTicketDetails" sender:indexPath];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(NSIndexPath *)selectedIndexPath {
if ([[segue identifier] isEqualToString:#"ShowTicketDetails"])
{
TicketDetailsViewController *tdv = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
long row = [myIndexPath row];
Ticket * currentTicket = [ticketsArray objectAtIndex:row];
tdv.tPriority = currentTicket.ticketPriority;
tdv.tId = currentTicket.ticketId;
tdv.tStatus = currentTicket.ticketStatus;
}
if ([[segue identifier] isEqualToString:#"ShowSendFeedback"]){
FeedbackViewController *fvc = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
long row = [myIndexPath row];
Ticket * currentTicket = [ticketsArray objectAtIndex:row];
fvc.tPriority = currentTicket.ticketPriority;
fvc.tId = currentTicket.ticketId;
fvc.tStatus = currentTicket.ticketStatus;
}
}
To be thorough, I've included my entire controller that has the issue.
#import "TicketsViewController.h"
#interface TicketsViewController ()
#end
#implementation TicketsViewController
#synthesize json, ticketsArray, ticketsTableView, currentTableViewType;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Tickets";
AppDataClass *appData=[AppDataClass getInstance];
currentTableViewType = appData.tableViewType;
[self retrieveData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return ticketsArray.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if([currentTableViewType isEqualToString:#"feedbackOnly"]){
return #"Requires Feedback";
} else {
return #"Issues";
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
Ticket * currentTicket = [ticketsArray objectAtIndex:indexPath.row];
cell.textLabel.text = currentTicket.ticketName;
cell.detailTextLabel.text = currentTicket.ticketAddress;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if([currentTicket.ticketPriority.lowercaseString isEqualToString:#"high"]) {
cell.imageView.image = [UIImage imageNamed:#"alert.png"];
if([indexPath row] % 2) [cell setBackgroundColor:[UIColor lightGrayColor]];
}
return cell;
}
#pragma mark - Methods
- (void)retrieveData
{
// NSURL * url = [NSURL URLWithString:getDataURL];
// NSData * data = [NSData dataWithContentsOfURL:url];
AppDataClass *appData=[AppDataClass getInstance];
NSString *args = #"userid=%#&authid=%#";
NSString *values=[NSString stringWithFormat:args, appData.userId, appData.authId];
json = [appData getPostData:appData.URL_LIST_TICKETS:values];
ticketsArray = [[NSMutableArray alloc] init];
// segeue names
// allTickets
// feedbackOnly
for(int i=0; i<json.count; i++){
NSString * tId = [[json objectAtIndex:i] objectForKey:#"id"];
NSString * tName = [[json objectAtIndex:i] objectForKey:#"name"];
NSString * tPriority = [[json objectAtIndex:i] objectForKey:#"priority"];
Ticket * myTicket = [[Ticket alloc] initWithTicketId:tId andTicketName:tName andTicketPriority:tPriority];
[ticketsArray addObject:myTicket];
}
[self.ticketsTableView reloadData];
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if([currentTableViewType isEqualToString:#"feedbackOnly"]){
[self performSegueWithIdentifier:#"ShowSendFeedback" sender:indexPath];
} else {
[self performSegueWithIdentifier:#"ShowTicketDetails" sender:indexPath];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(NSIndexPath *)selectedIndexPath {
if ([[segue identifier] isEqualToString:#"ShowTicketDetails"])
{
TicketDetailsViewController *tdv = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
long row = [myIndexPath row];
Ticket * currentTicket = [ticketsArray objectAtIndex:row];
tdv.tPriority = currentTicket.ticketPriority;
tdv.tId = currentTicket.ticketId;
tdv.tStatus = currentTicket.ticketStatus;
}
if ([[segue identifier] isEqualToString:#"ShowSendFeedback"]){
FeedbackViewController *fvc = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
long row = [myIndexPath row];
Ticket * currentTicket = [ticketsArray objectAtIndex:row];
fvc.tPriority = currentTicket.ticketPriority;
fvc.tId = currentTicket.ticketId;
fvc.tStatus = currentTicket.ticketStatus;
}
}
#end
Ok... so it seems to be a bug in XCode. I had originally copied the 2nd ViewController that I was trying to segue to and changed the class of it as well as some of the view components. I figured StoryBoard would be smart enough to reassign this view as its own. I was wrong. XCode didn't seem to like that. Starting from scratch with a new ViewController seems to fix everything and the segues are working correctly now. The exact same code works.
So if anyone is having this issue, make sure you didn't copy and paste a ViewController that you are trying to segue to. This will save you hours of headaches :-)
It probably had a reference to the same ViewController which is why whatever the last segue I setup was the only one working.

cellForRowAtIndexPath returns null but really need similar method

I have a UITableView in my UITableViewController (lol, obviously) but I need to get a cell at a given index inside the - (void)viewWillAppear:(BOOL)animated method.
Now, my cells are static and I create them in the interface builder. If I call
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:previously_selected_cell.integerValue inSection:0]];
it returns null for the cell. I only have 3 static cells in 1 sections. I tried both sections 0 and 1 and both return null.
Currently I have removed the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method because if I add it, it will clear the UITableView of all my static cells.
Is there a method I can call in - (void)viewWillAppear:(BOOL)animated that will return a cell at a given index?
Thanks in advance!
EDIT: I checked out this stackoverflow question but I'm using static cells without cellForRowAtIndexPath so that question didn't help. :(
EDIT2: I'm trying to set the accessory type of the cell when the view loads. But only on a certain cell, that cell being the one the user selected before he quit the app.
#import "AutoSyncSettings.h"
#import "CDFetchController.h"
#implementation AutoSyncSettings
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
CDFetchController *cdfc = [[CDFetchController alloc] init];
NSFetchedResultsController *results = [cdfc getFetchedResultsControllerWithEntityName:#"SETTINGS"];
NSArray *objects = [results fetchedObjects];
NSNumber *sync_setting;
if(objects.count > 0)
{
NSManagedObject *object = [objects objectAtIndex:0];
sync_setting = [object valueForKey:#"wifi_setting"];
NSLog(#"(Settings)sync_setting: %#",sync_setting);
NSLog(#"(Settings)sync_setting int value: %i",sync_setting.integerValue);
NSLog(#"(Settings)TableView: %#",self.tableView);
//cell is null, even after this.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:wifi_settings.integerValue inSection:0]];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//cell is still null. WHY OH WHY? :(
objects = nil;
}
cdfc = nil;
results = nil;
objects = nil;
sync_setting = nil;
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
for (int i = 0; i < [tableView numberOfRowsInSection:indexPath.section]; i++)
{
if([[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:indexPath.section]] accessoryType] == UITableViewCellAccessoryCheckmark)
{
[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:indexPath.section]].accessoryType = UITableViewCellAccessoryNone;
}
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
CDFetchController *cdfc = [[CDFetchController alloc] init];
NSFetchedResultsController *results = [cdfc getFetchedResultsControllerWithEntityName:#"SETTINGS"];
NSManagedObjectContext *context = [results managedObjectContext];
NSArray *objects = [results fetchedObjects];
if(objects.count > 0)
{
NSManagedObject *object = [objects objectAtIndex:0];
NSNumber *sync_setting = [NSNumber numberWithInt:indexPath.row];
[object setValue:sync_setting forKey:#"sync_interval"];
[object setValue:[NSNumber numberWithInt:0] forKey:#"id"];
[ErrorHandler saveMoc:context];
}
else
{
//INSERT NEW OBJECT
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:#"SETTINGS" inManagedObjectContext:context];
NSNumber *sync_setting = [NSNumber numberWithInt:indexPath.row];
[object setValue:sync_setting forKey:#"sync_interval"];
[object setValue:[NSNumber numberWithInt:0] forKey:#"id"];
[ErrorHandler saveMoc:context];
}
}
#end
I have a project doing exactly this and it works perfectly. However, it doesn't work unless you call [super viewWillAppear:animated] before trying to access the cells in this manner.
The base implementation presumably loads in the cells from the storyboard.
I want to add a checkmark accessory to the previously selected cell,
the previously_selected_cell variable gets stored even if the app
quits/crashes
The way to go will be to control the indexPath in your cellForRowAtIndexPath implementation and act if it's equal to previously_selected_cell.integerValue:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// usual cache lookup, allocation of the cell, etc
if (indexPath.row == previously_selected_cell.integerValue) {
// add checkbox here
} else {
// remove checkbox
}
}