delete row i uitableview working but cant reflect always on iphone - iphone

i can successfuly delete data from tableview , but when i go to main menu and come back then i see all the old data,
how to make data consistent , i.e once deleted it will be gone forever
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (DatabaseTestAppDelegate *)[[UIApplication sharedApplication] delegate];
{
appDelegate.favDetail = [[NSMutableArray alloc] initWithObjects:#"1", #"2",#"4",nil];
}
}
- (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] autorelease];
}
appDelegate = (DatabaseTestAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *cc=[appDelegate.favDetail objectAtIndex:indexPath.row];
NSLog(#" vale is %d",indexPath.row);
// Configure the cell...
NSArray *theParameters = [cc componentsSeparatedByString:#","];
NSLog(#"array is %#",cc);
NSLog(#"arraytheParameters is %#",theParameters);
cell.text=cc;//theParameters;
return cell;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{ NSLog(#"matrix is her%#",appDelegate.favDetail);
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[appDelegate.favDetail removeObjectAtIndex: indexPath.row];
[tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject: indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
/*
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
} */
}
- (void)viewWillAppear:(BOOL)animated
{ [tableView reloadData];
[super viewWillAppear:animated]; // no use , it shows old data
}
thanks

If you are looking to save the state of your model beyond the life of your table view controller, there are few things you can do. One is to write the array to a file in the documents directory and read it back on reload. This would work well will small sets of data. But if you are going to use a large data set, you have to use Core Data.
As for this specific case, you are reinitializing the data on every viewDidLoad. I suggest you do this in viewDidLoad –
...
if ( appDelegate.favDetail == nil ) {
appDelegate.favDetail = [[NSMutableArray alloc] initWithObjects:#"1", #"2",#"4",nil];
}
...
This will make sure that you don't reinitialize it.

you have to delete the data in both your view and your model

Check out the place where appDelegate.favDetail is getting data from...
While deleting you are removing from appDelegate.favDetail but When you go to main menu and come back you are reassigning the values to appDelegate.favDetail...
Checkout that appDelegate.favDetail only gets the value once.. or another option is you remove the data from the main source from where the favDetail gets the value
Happy iCoding....

Related

Change data source of tableView after selected row

I have table view with rows...after I selecting one item I want to show tableView with a new data source.
I tried to implement:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.searchDisplayController setActive:YES animated:YES];
Game *game = [self.filteredListContent objectAtIndex:indexPath.row];
//name your class names with capitals
NSMutableArray *arrayToBeAdded= [[NSMutableArray alloc]initWithArray:newgamearray];
[ListContent removeAllObjects];
[ListContent addObject:arrayToBeAdded];
but I getting exeption in the
[ListContent removeAllObjects];
Implementation of the init:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellID = #"cellSgames";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellID] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Gmage *game = [self.ListContent objectAtIndex:indexPath.row];
In the .h file i declare:
NSArray AllList;
NSMutableArray ListContent;
any ideas?
Instead of manipulating the current list, create new UITableViewController with your desired data source. If you are using the UINavigationController it will create a better user experience and you will avoid your current problem.
Example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
InnerTableViewController *innerTVC = [[InnerTableViewController alloc] initWithNibName:#"InnerTableViewController" bundle:nil];
[self.navigationController pushViewController:innerTVC animated:YES];
[innerTVC release];
}
Normally if you are resetting the array in didselect method and reloading your table view with new content it should work.
In your case i think at line:
[ListContent removeAllObjects];
ListContent is not a valid pointer. I don't see a reason to crash it here.

Reloading data on side-by-side UITableView

I am trying to create an application that has two UITableViews placed side-by-side. The left one lists article categories and the right one displays article previews (kind of like flipboard's search view).
On the left tableview's didSelectRowAtIndexPath, I am supposed to download the article and display the previews on the right UITableView. However, I cannot seem to make this work.
My assumption is that I reload the data on the tableview before the download is finished. Any suggestions?
EDITED:
Here's my current code:
- (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] autorelease];
if (tableView.tag == 1)
{
//if it's the left tableView (no problem here)
NSDictionary *catDic = [[Category categories] objectAtIndex:indexPath.row];
cell.textLabel.text = [catDic valueForKey:#"name"];
cell.textLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:[UIFont labelFontSize]];
}
if (tableView.tag == 2)
{
//if it's the right tableView
ArticlePreview *articleView = [[ArticlePreview alloc] initFlexibleHeightRowForArticleInfo:[self.articleInfos objectAtIndex:indexPath.row]];
//ArticlePreview is a custom class that create the articlePreview view,
//articleInfos is a variable that holds the articles in core data
[cell.contentView addSubview:articleView];
[articleView release];
}
}
return cell;
}
-(void) loadArticlePreview: (NSNumber *)_idx
{
[Category downloadArticlesforIndex:[_idx intValue]];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ArticleInfo" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
self.articleInfos = [context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
[self.articlePreviewTableView reloadData];
//articlePreviewTableView is the right table view identifier, hooked with IBOutlet and all
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.tag == 1) //if it's the left table
{
[self performSelectorInBackground:#selector(loadArticlePreview:) withObject:[NSNumber numberWithInt:indexPath.row]];
}
}
The problem is that the right tableview does not refresh. I think these methods are where the problem probably is.
According to your code, if you dequeue a UITableViewCell, its going to use the old cell, without any modifications for the actual cell that you need. Change it to so:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}//after this, use the tableView tag to identify.
You are also adding a content view to the preview table cell. I strongly recommend you create a custom UITableViewCell class when you do this. I found that to be the only way the adding subviews works in cells and is a lot easier to manage the cells with the custom class.
I assume you are doing the downloading in some method in the ArticlePreview. You don't need to reload the tableView once the download is finished. Since the ArticlePreview object has been added as the cell's subview, when the download is finished in it, call setNeedsDisplay when the view is content is downloaded.
You cannot reload your tableview in a background thread. You will have to create a method like this
-(void)reloadTable
{
[self.articlePreviewTableView reloadData];
}
Then call this method on the main thread inside the -(void) loadArticlePreview: (NSNumber *)_idx method
Hope this solves ur problem.

iPhone: How to add rows in tableview after tabelview already loaded?

I have implemented "Add to Favourites" functionality for my iPhone application. It works fine except adding cells into my Favourite Table View during runtime. For example, I have given following methods.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
tableView.hidden = YES;
warningLabel.hidden = YES;
// Load any change in favourites
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:kFavouriteItemsKey];
self.favourites = [NSKeyedUnarchiver unarchiveObjectWithData:data];
if([self.favourites count] > 0)
tableView.hidden = NO;
else
warningLabel.hidden = NO;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.favourites count]; // Favorites is a dictionary contains required data
}
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat:#"index: %d",indexPath.row];
return cell;
}
This code works fine and display rows correctly for the first time only! After tableview is loaded and if I add new item(s) in favorites or delete any item(s), it doesn't make any difference to my tableview! I want to display exactly what is available in Favourites dictionary. It seems CellForRowAtIndexPath doesn't get invoked when ViewAppear again. Is there any method for TableView that I can use to achieve my requirements?
I think you've missed to call [tableView reloadData];
The very easy way is to just call [tableView reloadData] whenever you make any changes.
There is also a better (faster for large tables, and possibly animated; more elegant), but much more complicated way which I won't go into unless you decide the reloadData way isn't sufficient for you.

iPhone - Array to UITableView

I can't display array in UITableView. The thing I do is - in viewWILLappear I'm creating array. In viewDIDappear I'm filling the array. But when I run [myArr count] or [myArr objectAtIndex:indexPath.row] in table setup I get empty table. If I define constant integer as row count and some constant string as cell text everything works fine. Is there some populate() method I have to run or is it a problem with some order of declarations?
Thanks for any help. Here's the code:
- (void)viewWillAppear:(BOOL)animated {
myArr = [[NSMutableArray alloc] initWithCapacity:100];
}
- (void)viewDidAppear:(BOOL)animated {
[self load_array];
}
- (void) load_array {
for (SomeObject *someObject in SomeObjects) {
[myArr addObject:someObject.someString];
NSLog(#"Value: %#", [myArr objectAtIndex:([myArr count]-1)]); // works
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [myArr count]; // works if I return const ("return 2")
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (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] autorelease];
}
cell.textLabel.text = [myArr objectAtIndex:indexPath.row]; //=#"ASDF" works.
return cell;
}
You need to perform reloadData on your table view to make the view re-load the table cells.
Update: You should not allocate your array in the viewWillAppear, as this method might be called several times. Construct the array in the viewDidload: and fill it there, or in a background thread, or in the viewWillAppear: (using a conditional statement to check if its already filled). You should also make sure that you do not create a memory leak, from the code you provided it is likely that myArr will be replaced by a newly allocated array without being released.

How can a checkmark state be saved in core data?

I have a list app where users hit the + button and enter in an item that they want to appear in the list and hit save. The table is saved with core data. The only problem is when the cell is taped I want a checkmark to be displayed. Ive enabled multiple selection with
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone) {
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
I would like the checkmarks to be persisted in the cell after the user exits. I have created an attribute in my entity called "checks" and gave it the type of boolean but I dont know how to make it where if you hit a row then a check appears and is persisted. Any help would be greatly appreciated. Thanks
This is how I do it. One notable point: CoreData does not store booleans, so any property labeled "boolean" is actually of type NSNumber. You've got to remember to convert back and forth when dealing with CoreData and boolean values.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *selectedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([[selectedObject valueForKey:#"isDone"] boolValue]) {
[selectedObject setValue:[NSNumber numberWithBool:NO] forKey:#"isDone"];
} else {
[selectedObject setValue:[NSNumber numberWithBool:YES] forKey:#"isDone"];
}
}
I have my UITableViewController set as the the delegate for the NSFetchedResultsController, so the changes I made to the managed objects in the query ^^^ will cause the following two methods to be run.
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *defaultCellIdentifier = #"Item";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:defaultCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:defaultCellIdentifier] autorelease];
}
NSManagedObject *item = [[self fetchedResultsController] objectAtIndexPath:indexPath];
cell.textLabel.text = [item valueForKey:#"name"];
if ([[item valueForKey:#"checks"] boolValue]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Here's how everything ties together
User clicks on a row
tableView:didSelectRow... method changes the "isDone" property of the appropriate managed object.
the fetched results controller notices that a managed object has changed and calls the controllerDidChangeContent method on its delegate.
My controllerDidChangeContent method just reloads all the data in the table view
When the tableView is reloaded, my tableView:cellForRow... method checks the "isDone" property of the managed item to see if the cell should have a checkmark or not.
And just so you don't get confused, I initially used a generic NSMangagedObject to store row state, which is why the first method I posted says, [selectedObject valueForKey:#"isDone"]. Later I switched to a subclassed managed object named JKItem, which is why the second set of methods is able to use item.isDone without generating a compiler warning.