Use moveRowAtIndexPath - iphone

I'm trying to find a code sample that shows how to handle moving/rearranging cells in a tableView.
For removal of Core data I use the code that is written below
- (void)tableView:(UITableView *)aTableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription* entityDescription = [NSEntityDescription entityForName:#"MyBase"
inManagedObjectContext:self.objectContext];
[fetchRequest setEntity:entityDescription];
NSArray *empArray=[self.objectContext executeFetchRequest:fetchRequest error:nil];
if ([empArray count] > 0){
Moneybox *employee = [empArray objectAtIndex:indexPath.row];
[self.objectContext deleteObject:employee];
[self.objectContext save:nil];
}
[self buscarContactoExistente];
[myTable reloadData];
}
}
How do I make
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
in the same style?

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
      toIndexPath:(NSIndexPath *)toIndexPath
{
    Moneybox *employee = [empArray objectAtIndex:fromIndexPath.row];
    [empArray removeObject: employee];
    [empArray insertObject:employee atIndex:toIndexPath.row];
}

Related

To display correct value of NSManagerObject on cell.textLabel.text

I am newbie with Xcode 5 and start do some coding with appcode.com's tutorial.
I can't get the the proper search result printing back to tableview(core data), any suggestion will be highly appreciated, thanks in advance! cheers.
#import "RecipeStoreTableViewController.h"
#import "AddRecipeViewController.h"
#interface RecipeStoreTableViewController () {
NSMutableArray *recipes;
NSArray *searchResults;
}
#end
#implementation RecipeStoreTableViewController
- (NSManagedObjectContext *)managedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate performSelector:#selector(managedObjectContext)]) {
context = [delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Fetch the recipes from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Recipe"];
recipes = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
// NSLog(#"test %#", [recipes valueForKey:#"name"]);
// Reload table data
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (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.
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 = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSManagedObject *recipe = [recipes objectAtIndex:indexPath.row];
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults valueForKey:#"name"];
NSString *description = [[NSString alloc] initWithFormat:#"%# - %#", [searchResults valueForKey:#"image"], [searchResults valueForKey:#"prepTime"]];
cell.detailTextLabel.text = description;
}else{
cell.textLabel.text = [recipe valueForKey:#"name"];
NSString *description = [[NSString alloc] initWithFormat:#"%# - %#", [recipe valueForKey:#"image"], [recipe valueForKey:#"prepTime"]];
cell.detailTextLabel.text = description;
}
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *context = [self managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete object from database
[context deleteObject:[recipes objectAtIndex:indexPath.row]];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Can't Delete! %# %#", error, [error localizedDescription]);
return;
}
// Remove recipe from table view
[recipes removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"UpdateRecipe"]) {
NSManagedObject *selectedRecipe = [recipes objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
UINavigationController *destViewController = segue.destinationViewController;
AddRecipeViewController *recipeViewController = (AddRecipeViewController*)destViewController.topViewController;
recipeViewController.recipe = selectedRecipe;
}
}
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", searchText];
searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
#end
You are calling the valueForKey on NSMutableArray object, which should be called on NSManagedObject
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSManagedObject *recipe;
if (tableView == self.searchDisplayController.searchResultsTableView)
recipe = searchResults[indexPath.row];
else
recipe = recipes[indexPath.row];
cell.textLabel.text = [recipe valueForKey:#"name"];
NSString *description = [[NSString alloc] initWithFormat:#"%# - %#", [recipe valueForKey:#"image"], [recipe valueForKey:#"prepTime"]];
cell.detailTextLabel.text = description;
return cell;
}

UISearchBar with scope buttons NSInternalInconsistencyException Crash on Cancel

I'm at sort of a loss here.
I have a UISearchBar with two scope buttons Option A and Option B. Searching works just fine on both scope buttons but when I click Cancel out of the search bar with the second scope button selected the app will sometimes crash with this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no object at index 3 in section at index 0'
Here's the relevant code for my UITableView:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSArray *results = [fetchedResultsController fetchedObjects];
return [[fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (tableView == self.tableView && [[fetchedResultsController sections] count] > section) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo name];
}
return nil;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSArray *alphabet = [NSArray arrayWithObjects:UITableViewIndexSearch, #"A", #"B", #"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z",#"#",nil];
if (tableView == self.tableView) {
return alphabet;
}
return nil;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
if(tableView == self.tableView && [title isEqual:UITableViewIndexSearch]){
[tableView scrollRectToVisible:[[tableView tableHeaderView] bounds] animated:NO];
return -1;
} else if (tableView == self.tableView) {
return [self.fetchedResultsController.sectionIndexTitles indexOfObject:title];
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"OptionACell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSManagedObject *category = [fetchedResultsController objectAtIndexPath:indexPath];
if (self.searchBar.selectedScopeButtonIndex == CategoriesViewSearchScopeOptionB && ![self.searchBar.text isEqual:#""]) {
[cell.textLabel setText:[category valueForKey:#"text"]];
} else {
[cell.textLabel setText:[category valueForKey:#"name"]];
}
return cell;
}
And the UISearchBar:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if([self.searchBar.text isEqual: #""] && self.searchBar.selectedScopeButtonIndex == CategoriesViewSearchScopeOptionB) {
self.searchBar.text=#"";
[self updateOptionAFetchRequest];
} else {
[self updateFetchRequest];
NSFetchedResultsController *fetchController = [self fetchedResultsController];
}
}
- (void)searchBarCancelButtonClicked:(UISearchBar *) searchBar {
[self logSearchTerm:self.searchBar.text];
self.searchBar.text = #"";
self.searchBar.selectedScopeButtonIndex = CategoriesViewSearchScopeOptionA;
[self updateOptionAFetchRequest];
self.searchDisplayController.delegate = nil;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
[self logSearchTerm:self.searchBar.text];
if([self.searchBar.text isEqual: #""]) self.searchBar.selectedScopeButtonIndex = CategoriesViewSearchScopeOptionA;
return YES;
}
- (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope {
if([self.searchBar.text length] > 0) {
[self updateFetchRequest];
}
}
- (void)updateFetchRequest {
if (self.searchBar.selectedScopeButtonIndex == CategoriesViewSearchScopeOptionB) {
[self updateOptionBFetchRequest];
return;
}
[self updateOptionAFetchRequest];
}
I'm having trouble discerning the exact pattern of the crashing. It seems to crash consistently whenever I perform the action of opening the UISearchBar, clicking OptionB then Canceling. But when I open the SearchBar, click back and forth between the scope buttons and perform a couple searches, I'm able to close no problem.
Any help from Core Data experts would be greatly appreciated.

Getting bad access while deleting cell and reloading table view

I am trying to build a table using custom UITableViewCell, but after deleting cell and when I try load the view, I get an EXC_BAD_ACCESS error,here i'm getting data from a dictionary and loading it to table view.
The code for my Table is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell = (uploadCustomCell *)[tabelView1 dequeueReusableCellWithIdentifier:#"cell"];
[cell setSelectionStyle:UITableViewCellEditingStyleNone];
if (cell == nil) {
[[NSBundle mainBundle]loadNibNamed:#"uploadCustomCell" owner:self options:nil];
cell = (uploadCustomCell *)self.uploadCustomcell;
}
saveBtnCcell.hidden = YES;
cell.textNamefield.hidden = YES;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.defaultSwitch setEnabled:NO];
NSMutableArray *dictionary = [contents objectAtIndex:indexPath.row];
NSLog(#"dict dict :%#",dictionary);
//
cell.nameLabelCell.text = [dictionary valueForKey:#"VideoName"];
cell.userName.text = [dictionary valueForKey:#"User"];
NSString *defaultVideo = [dictionary valueForKey:#"DefaultVideo"];
if ([defaultVideo isEqualToString:#"1"]) {
[cell.defaultSwitch setOn:YES animated:YES];
}
else {
[cell.defaultSwitch setOn:NO animated:YES];
}
[cell.defaultSwitch addTarget:self action:#selector(setState:) forControlEvents:UIControlEventValueChanged];
cell.thumbImg.image = [arrayimage objectAtIndex:indexPath.row];
VideoNameTextField.hidden = YES;
return cell;
}
- (void)setState:(id)sender {
state = [sender isOn];
// NSString *rez = state == YES ? #"YES" : #"NO";
NSLog(#"state.........:%d",state);
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"height:%f",uploadCustomcell.frame.size.height);
return 207;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *dictionary = [contents objectAtIndex:indexPath.row];
NSLog(#"Dictionary:%#",dictionary);
NSLog(#"indexpath:%#",indexPath);
//
NSLog(#"at index%d obj:%#",indexPath.row,dictionary);
NSString *nameDetails = [dictionary valueForKey:#"VideoName"];
guid = [dictionary valueForKey:#"GUID"];
detailsNameLbl.text = nameDetails;
detailsVehImg.image = [arrayimage objectAtIndex:indexPath.row];;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:
(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[contents removeObjectAtIndex:indexPath.row];
[tabelView1 reloadData];
}
}
Try this:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
You must use this method also:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[contents removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//[tabelView1 reloadData];
}

iPhone -- breaking up Core Data into sections with NSFetchResultsController

So I have successfully implemented Core Data to retrieve objects from a server, save them, and display them in a UITableView. However now, I wish to break these up into separate sections. I have looked for a few days now, and NSFetchedResultsController seems to confuse me, even though the way I am using it works. I have a key in my Entity called "articleSection" that is set when the item is added to Core Data with items such as "Top" "Sports" "Life". How would I go about breaking these into separate sections in my UITableView? I have read about using multiple NSFetchedResultsControllers, but I am about as frustrated as can be with this.
Any suggestions or help would be greatly appreciated.
The documentation for NSFetchedResultsController has sample code that works perfectly.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = /* get the cell */;
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Configure the cell with data from the managed object.
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo name];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [self.fetchedResultsController sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
Set the sortDescriptors of the fetch request so the results are sorted by articleSection.
Set the sectionKeyPath to "articleSection" so the NSFetchedResultsController creates the sections for you. Something like this:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Item" inManagedObjectContext:self.managedObjectContext];;
request.fetchBatchSize = 20;
// sort by "articleSection"
NSSortDescriptor *sortDescriptorCategory = [NSSortDescriptor sortDescriptorWithKey:#"articleSection" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:sortDescriptorCategory, nil];;
// create nsfrc with "articleSection" as sectionNameKeyPath
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"articleSection" cacheName:#"MyFRCCache"];
frc.delegate = self;
NSError *error = nil;
if (![frc performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
self.fetchedResultsController = frc;

Optimizing UITableView

I have a UITableview made up with a custom cell loaded from a nib. This custom cell has 9 UILabel s and thats all. When scrolling the table on my iPhone the tables scrolling motion is slightly jerky, its not as smooth as other tableviews! (On the simulator it scrolls fine but I guess its using the extra power of my mac)
Are there any tips to help optimize this or any tableview or methods to help find the bottleneck.
Many Thanks
UPDATE:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return [[fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
//Returns the title for each section header. Title is the Date.
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
NSArray *objects = [sectionInfo objects];
Data *myData = [objects objectAtIndex:0];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterLongStyle];
NSDate *headerDate = (NSDate *)myData.dataDate;
NSString *headerTitle = [formatter stringFromDate:headerDate];
[formatter release];
return headerTitle;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *dataEntryCellIdentifier = #"dataEntryCellIdentifier";
DataEntryCell *cell = (DataEntryCell *)[tableView dequeueReusableCellWithIdentifier:dataEntryCellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DataEntryCell" owner:self options:nil];
cell = self.dataEntryCell;
self.dataEntryCell = nil;
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
//Method to setup the labels in the cell with managed object content.
- (void)configureCell:(DataEntryCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Data *myData = [fetchedResultsController objectAtIndexPath:indexPath];
cell.label1.text = myData.data1;
cell.label2.text = myData.data2;
cell.label3.text = myData.data3;
cell.label4.text = myData.data4;
cell.label5.text = myData.data5;
cell.label6.text = myData.data6;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//Check to see if its in Delete mode
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Delete Object from context.
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
[context deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];
//Save Context to persitant store
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Delete Error");
exit(-1);
}
}
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Table is not to be manually reordered
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Create a detailView instance.
DetailViewController *detailView = [[DetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
//Pass selected data to the detailView.
Data *myData = [fetchedResultsController objectAtIndexPath:indexPath];
detailView.myData = myData;
//Push the detailView onto the Nav stack.
[self.navigationController pushViewController:detailView animated:YES];
[detailView release];
}
Take a look at this question, which references the author of Tweetie. In short: do your drawing manually, not using subviews.
The original Tweetie article can now be found here.