Delete Firebase Data located at indexPath.row - objective-c

Been trying to figure this out for a while and I cannot understand why this keeps crashing. I swipe the cell and the delete button shows up, but when pressed it crashes at:
[[[_datRef child:#"posts"]child:index] removeValue];
Crash code is this:
***** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FIRDataSnapshot length]: unrecognized selector sent to instance 0x61800002a080**
I'm trying to delete the Firebase content at the row that was selected for deletion. Anyone know what I am missing? Please only Objective-C.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return finalArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UpdatesTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"updateCell" forIndexPath:indexPath];
FIRDataSnapshot *snapshot = (self.finalArray)[indexPath.row];
NSString *title = snapshot.value[#"title"];
NSString *description = snapshot.value[#"description"];
NSString *date = snapshot.value[#"date"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
cell.titleLabel.text = title;
cell.updateTextView.text = description;
NSString *timeAgoFormattedDate = [NSDate mysqlDatetimeFormattedAsTimeAgo:date];
cell.dateLabel.text = timeAgoFormattedDate;
cell.updateTextView.delegate = self;
cell.clipsToBounds = YES;
return cell;
}
- (void)getUpdates {
posts = [_datRef child:#"posts"];
[[posts queryOrderedByChild:#"date"] observeEventType:FIRDataEventTypeValue
withBlock:^(FIRDataSnapshot *snapshot) {
self.updatesArray = [NSMutableArray array];
for (snapshot in snapshot.children) {
[self.updatesArray addObject:snapshot];
_sortArray = [updatesArray reverseObjectEnumerator].allObjects;
self.finalArray = [NSMutableArray array];
[self.finalArray addObjectsFromArray:_sortArray];
}
[self.tableView reloadData];
}];
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[[_datRef child:#"posts"] removeValue];
[finalArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

I found an easier way of doing this. In your post method:
//Create a random string for you child:
NSString *uuid = [NSUUID UUID].UUIDString;
//Put the random string as one of your childs:
[[[_alertRef child:#"posts"] child:uuid] setValue:#{
//create a key called childID and assign it the same value:
#"childID" : uuid,
#"date" : _date,
#"description" : _descriptionTextView.text,
#"title" : _alertTitle.text }];
Now when you go to retrieve your firebase data in your tableView put the data in a dictionary:
- (void)getUpdates {
posts = [_datRef child:#"posts"];
[[posts queryOrderedByChild:#"date"] observeEventType:FIRDataEventTypeValue
withBlock:^(FIRDataSnapshot *snapshot) {
self.updatesArray = [NSMutableArray array];
for (snapshot in snapshot.children) {
[self.updatesArray addObject:snapshot];
_firebaseDict = [[NSDictionary alloc] init];
_firebaseDict = snapshot.value;
_sortArray = [updatesArray reverseObjectEnumerator].allObjects;
self.finalArray = [NSMutableArray array];
[self.finalArray addObjectsFromArray:_sortArray];
}
[self.tableView reloadData];
}];
[self.tableView reloadData];
}
Then in your tableView editing method:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString *childID = [_firebaseDict valueForKey:#"childID"];
[[[_datRef child:#"posts"] child:childID] removeValue];
[finalArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}

Related

How to show UISearchbar bar only in tableview not on UINavigationbar in objective c

I am new in ios and I am facing problem regarding to UISearchbar. I have done code like this
.h
IBOutlet UITableView *table;
NSArray *recipes;
NSArray *searchResults;
.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
recipes = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee", #"White Chocolate Donut", #"Starbucks Coffee", #"Vegetable Curry", #"Instant Noodle with Egg", #"Noodle with BBQ Pork", #"Japanese Noodle with Pork", #"Green Tea", #"Thai Shrimp Cake", #"Angry Birds Cake", #"Ham and Cheese Panini", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [recipes count];
}
}
- (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 (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
}
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
But it shows me search bar on navigation bar
But I need to show it on the UItableView itself. Like this in Image
Thanks in advance
I have use code to search from 4 mutable array...
- (void)viewDidLoad {
[super viewDidLoad];
[searchtxt addTarget:self action:#selector(textFieldDidChangeClose:) forControlEvents:UIControlEventEditingChanged];
searchtxt.delegate=self;
}
#pragma mark - Seach Button...
-(void)textFieldDidChangeClose:(UITextField *)textField
{
searchTextString=textField.text;
[self updateSearchArray:searchTextString];
}
-(void)updateSearchArray:(NSString *)searchText
{
if(searchText.length==0)
{
isFilter=NO;
[table reloadData];
}
else{
isFilter=YES;
searchArray=[[NSMutableArray alloc]init];
searchArrayId=[[NSMutableArray alloc] init];
searchArraystatus=[[NSMutableArray alloc] init];
searchArraydescription=[[NSMutableArray alloc] init];
for(NSString *string in idarray){
NSRange stringRange=[string rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(stringRange.location !=NSNotFound){
[searchArray addObject:string];
NSInteger index = [idarray indexOfObject:string];
[searchArraystatus addObject:[shortnamearray objectAtIndex:index]];
[searchArraydescription addObject:[descarray objectAtIndex:index]];
[searchArrayId addObject:[complaintidArray objectAtIndex:index]];
}
}
[table reloadData];
}
}
#pragma mark - TableView Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(isFilter)
{
return [searchArray count];
}
else
{
return [idarray count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *STI=#"STI";
IBTClosedComplaintCell *cell = (IBTClosedComplaintCell *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:STI];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"IBTClosedComplaintCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.accessoryType=UITableViewCellAccessoryNone;
}
if(isFilter)
{
cell.Complaintnamelbl.text=[NSString stringWithFormat:#"%#",[searchArray objectAtIndex:indexPath.row]];
cell.statuslbl.text = [NSString stringWithFormat:#"%#",[searchArraystatus objectAtIndex:indexPath.row]];
cell.descriptiolbl.text=[NSString stringWithFormat:#"%#",[searchArraydescription objectAtIndex:indexPath.row]];
cell.complaintidlbl.text = [NSString stringWithFormat:#"%#",[searchArrayId objectAtIndex:indexPath.row]];
}
else
{
cell.Complaintnamelbl.text=[idarray objectAtIndex:indexPath.row];
cell.statuslbl.text=[shortnamearray objectAtIndex:indexPath.row];
cell.descriptiolbl.text=[descarray objectAtIndex:indexPath.row];
cell.complaintidlbl.text=[NSString stringWithFormat:#"%#",[complaintidArray objectAtIndex:indexPath.row]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
IBTClosedNextScreen *next =[[IBTClosedNextScreen alloc] initWithNibName:#"IBTClosedNextScreen" bundle:nil];
[self.navigationController pushViewController:next animated:YES];
if(isFilter)
{
str1=[NSString stringWithFormat:#"%#",[searchArrayId objectAtIndex:indexPath.row]];
NSLog(#"String =%#",str1);
next.str =str1;
}
else
{
str1=[NSString stringWithFormat:#"%#",[self.complaintidArray objectAtIndex:indexPath.row]];
NSLog(#"String =%#",str1);
next.str =str1;
}
}

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

Search bar in tableview using objective c with parse database

I've been following a tutorial teaching how to make a tableview with a search bar. I got this to work without problems, but now I learned to make the same tableview but instead of local arrays, I've been getting my data from parse as PFObjects.
I then tried to take the search bar and implant it in my new tableview which uses parse. I can't get this to work. Following the tutorial with the search bar they are using simple arrays stored locally..
Can anyone point me in the right direction of how to use a search bar in a tableview that gets its data from a parse database?
This is my code that works with my tableview that does NOT use parse.
#implementation RecipeBookViewController {
NSArray *recipes;
NSArray *searchResults;
}
#synthesize tableView = _tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Initialize table data
recipes = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto",
#"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee",
nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [recipes count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath
- *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
[self performSegueWithIdentifier: #"showRecipeDetail" sender: self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
RecipeDetailViewController *destViewController =
segue.destinationViewController;
NSIndexPath *indexPath = nil;
if ([self.searchDisplayController isActive]) {
indexPath = [self.searchDisplayController.searchResultsTableView
indexPathForSelectedRow];
destViewController.recipeName = [searchResults
objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForSelectedRow];
destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
}
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:
(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
#pragma mark - UISearchDisplayController delegate methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar
scopeButtonTitles]
objectAtIndex:
[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
And this is my tableview which get its data from my parse database:
#implementation RecipeBookViewController {
}
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [super initWithCoder:aCoder];
if (self) {
// Custom the table
// The className to query on
self.parseClassName = #"Recipe";
// The key of the PFObject to display in the label of the default cell
style
self.textKey = #"name";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = NO;
// The number of objects to show per page
//self.objectsPerPage = 10;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshTable:)
name:#"refreshTable"
object:nil];
}
- (void)refreshTable:(NSNotification *) notification
{
// Reload the recipes
[self loadObjects];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"refreshTable"
object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (PFQuery *)queryForTable
{
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
// If no objects are loaded in memory, we look to the cache first
to fill the table
// and then subsequently do a query against the network.
/* if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}*/
// [query orderByAscending:#"name"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:
(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *simpleTableIdentifier = #"RecipeCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
PFFile *thumbnail = [object objectForKey:#"imageFile"];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = [UIImage imageNamed:#"placeholder.jpg"];
thumbnailImageView.file = thumbnail;
[thumbnailImageView loadInBackground];
UILabel *nameLabel = (UILabel*) [cell viewWithTag:101];
nameLabel.text = [object objectForKey:#"name"];
UILabel *prepTimeLabel = (UILabel*) [cell viewWithTag:102];
prepTimeLabel.text = [object objectForKey:#"prepTime"];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:
(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath*) indexPath
{
// Remove the row from data model
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
[self refreshTable:nil];
}];
}
- (void) objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
NSLog(#"error: %#", [error localizedDescription]);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showRecipeDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController =
segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Recipe *recipe = [[Recipe alloc] init];
recipe.name = [object objectForKey:#"name"];
recipe.imageFile = [object objectForKey:#"imageFile"];
recipe.prepTime = [object objectForKey:#"prepTime"];
recipe.ingredients = [object objectForKey:#"ingredients"];
destViewController.recipe = recipe;
}
}

Objective-C array issues

I have this NSArray and each item returns a POIndex and PONumber and I am putting each item of the array inside another Array and the other array is returning like this:
POIndex
PONumber
POIndex
PONumber
Here is my code:
- (void)GetRequest
{
NSArray *tableData = [dataSource.areaData GetPurchaseOrderItems:[NSString stringWithFormat:#"%#%#",areaPickerSelectionString,unitPickerSelectionString]];
if(!self.objects){
self.objects = [[NSMutableArray alloc]init];
}
for(int i = 0; i < [tableData count]; i++){
[self.objects addObjectsFromArray:[tableData objectAtIndex:i]];
}
[self.tableView reloadData];
}
Here is a screenshot of what tableData is returning:
What I am looking to do is have have the PONumber as the key and POIndex as the display value, how would I do this?
I have tried the following:
NSMutableDictionary *subDict=[[NSMutableDictionary alloc]init];
for (NSDictionary *dict in tableData) {
[subDict setValue:[dict objectForKey:#"POIndex"] forKey:[dict objectForKey:#"PONumber"]];
[self.objects addObject:subDict];
}
but this displays like so:
{
{
{
{
Here is what is displaying it:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *object = self.objects[indexPath.row];
cell.textLabel.text = [object description];
return cell;
}
Your tableData array contains NSDictionary at each index. So you can use the same array in your cellForRowIndexPath method like as follows,
#property(nonatomic, retain) NSArray * tableData;
- (void)GetRequest
{
self.tableData = [dataSource.areaData GetPurchaseOrderItems:[NSString stringWithFormat:#"%#%#",areaPickerSelectionString,unitPickerSelectionString]];
[self.yourTableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *strPOIndex = [self.tableData[indexPath.row] valueForKey:#"POIndex"];
cell.textLabel.text = strPOIndex;
return cell;
}

multiple checkmarks from

Tutorial I am following: http://www.appcoda.com/ios-programming-tutorial-create-a-simple-table-view-app/
I have created a tableview with 16 cells. When I select a row, it will show checkmark on it.
But when I scroll the tableview, there is also a checkmark showing on another cell further down the list. This repeats for any cell selected.
#import "FlightChecklistViewController.h"
#interface FlightChecklistViewController ()
#end
#implementation FlightChecklistViewController
{
NSArray *tableData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Initialize table data
tableData = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee", #"White Chocolate Donut", #"Starbucks Coffee", #"Vegetable Curry", #"Instant Noodle with Egg", #"Noodle with BBQ Pork", #"Japanese Noodle with Pork", #"Green Tea", #"Thai Shrimp Cake", #"Angry Birds Cake", #"Ham and Cheese Panini", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"You've selected a row" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display Alert Message
[messageAlert show];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
Any suggestions?
You need to store the information about the rows indexpaths, that were selected, somehow.
And populate your cell according to it.
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSMutableArray *selectedCells;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.selectedCells = [NSMutableArray array];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 100;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *unifiedID = #"aCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:unifiedID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:unifiedID];
}
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
//if the indexPath was found among the selected ones, set the checkmark on the cell
cell.accessoryType = ([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
//if a row gets selected, toggle checkmark
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]){
[self.selectedCells removeObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
[self.selectedCells addObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
-(BOOL)isRowSelectedOnTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{
return ([self.selectedCells containsObject:indexPath]) ? YES : NO;
}
#end
you will find the complete example code on github
The problem is that cells are reused. So, if you add a checkmark accessory view to a cell further up it'll appear again when the cell is reused further down. You should save which ones are checkmarked in an array somewhere that correlates to the rows of the table when you add/remove a checkmark. Then, when you give the table view a new cell you can determine whether or not it needs a checkmark and set that up.
I had the same issue recently with one of my apps, and I fixed it by doing this:
#property (nonatomic, strong) NSArray *list;
- (void)viewDidLoad
{
[super viewDidLoad];
self.list = [[NSArray alloc] initWithObjects:#"foo", #"bar", nil];
}
- (NSString *)SettingsPlist
{
NSString *paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *PlistPath = [paths stringByAppendingPathComponent:#"Settings.plist"];
return PlistPath;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [[self list] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *contentForThisRow = [[self list] objectAtIndex:[indexPath row]];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:[self SettingsPlist]];
NSString *row = [NSString stringWithFormat:#"%d",indexPath.row];
if([[dict objectForKey:row]isEqualToString:#"0"])
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[[cell textLabel] setText:contentForThisRow];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithContentsOfFile:[self SettingsPlist]];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *row = [NSString stringWithFormat:#"%d",indexPath.row];
if(cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSString *on = #"1";
[plist setObject:on forKey:row];
[plist writeToFile:[self SettingsPlist] atomically:YES];
}
else if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSString *off = #"0";
[plist setObject:off forKey:row];
[plist writeToFile:[self SettingsPlist] atomically:YES];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}