RSS

Core Data Basics Part 3 – Editing and Deleting

14 Feb


Introduction

In this Part 3 of Core Data Basics I’ll explain:

  • Editing Existing Data
  • Deleting Existing Data

Prerequisites

We follow on from Part 2 where we’ve already created a simple Storyboard app with delegation.  Download the project from the end of Part 2 then extract and open it with Xcode.

Editing Existing Data

To edit Roles we’re going to need a new Table View Controller called RoleDetailTVC. RoleDetailTVC will be very similar to AddRoleTVC except that roleNameTextField will be populated with existing data.

Create a new RoleDetailTVC class by clicking File > New > New File then create a new UIViewController subclass:

Ensure you select UITableViewController and call it RoleDetailTVC:

Next open MainStoryboard.storyboard then drag select the whole Add Role Table View Controller:

Click Edit > Duplicate which will create a copy of the Add Role Table View Controller on top of the existing one.  Rearrange them so they look like this:

Hold down Control while you drag a line from the Roles Prototype Cell to the copy of the Add Role Table View Static Content area. This should create a Segue so select Push when asked.  The copy of the Add Role Table View Controller should now be embedded in the Navigation View Controller:

Set the Navigation Item Title of the copied Table View Controller to Role Detail:

Rename the new Storyboard Segue to Role Detail Segue:

Select the Role Detail Table View Controller and set the Class to RoleDetailTVC:

Replace all the code in RoleDetailTVC.h with all the code from AddRoleTVC.h.  In RoleDetailTVC.h replace the text AddRoleTVC with the text RoleDetailTVC: (hint use Command+F then change Find to Replace)

Replace all the code in RoleDetailTVC.m with all the code from AddRoleTVC.m.  In RoleDetailTVC.m replace the text AddRoleTVC with the text RoleDetailTVC:

Add the following to RoleDetailTVC.h:

@property (strong, nonatomic) Role *role;

Add the following to RoleDetailTVC.m

@synthesize role = _role;

Add the following method to the top of RoleDetailTVC.m (under @implementation). This method is responsible for populating roleNameTextField with the current role name:

- (void)viewDidLoad 
{
    NSLog(@"Setting the value of fields in this static table to that of the passed Role");
    self.roleNameTextField.text = self.role.name;
    [super viewDidLoad];
}

Edit the save method in RoleDetailTVC.m so it looks exactly as follows:

- (IBAction)save:(id)sender
{
    NSLog(@"Telling the AddRoleTVC Delegate that Save was tapped on the AddRoleTVC");
    [self.role setName:roleNameTextField.text];
    [self.managedObjectContext save:nil];  // write to database
    [self.delegate theSaveButtonOnTheRoleDetailTVCWasTapped:self];
}

Add/edit the following lines to the appropriate area in RolesTVC.h:

#import "RoleDetailTVC.h" // so this class can be an RoleDetailTVCDelegate
@interface RolesTVC : CoreDataTableViewController 
@property (strong, nonatomic) Role *selectedRole;

Add the following lines to the appropriate area in RolesTVC.m:

@synthesize selectedRole;

Completely replace the existing prepareForSegue method in RolesTVC.m with the following. You will notice I’ve just put an else/if that refers to the new segue.  The comments explain the rest:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
	if ([segue.identifier isEqualToString:@"Add Role Segue"])
	{
        NSLog(@"Setting RolesTVC as a delegate of AddRolesTVC");
 
        AddRoleTVC *addRoleTVC = segue.destinationViewController;
        addRoleTVC.delegate = self;
        addRoleTVC.managedObjectContext = self.managedObjectContext;
	}
    else if ([segue.identifier isEqualToString:@"Role Detail Segue"])
    {
        NSLog(@"Setting RolesTVC as a delegate of RoleDetailTVC");
        RoleDetailTVC *roleDetailTVC = segue.destinationViewController;
        roleDetailTVC.delegate = self;
        roleDetailTVC.managedObjectContext = self.managedObjectContext;
 
        // Store selected Role in selectedRole property
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        self.selectedRole = [self.fetchedResultsController objectAtIndexPath:indexPath];
 
        NSLog(@"Passing selected role (%@) to RoleDetailTVC", self.selectedRole.name);
        roleDetailTVC.role = self.selectedRole;
    }
    else {
        NSLog(@"Unidentified Segue Attempted!");
    }
}

Add the following method to the bottom of RolesTVC.m (above @end)

- (void)theSaveButtonOnTheRoleDetailTVCWasTapped:(RoleDetailTVC *)controller
{
    // do something here like refreshing the table or whatever
 
    // close the delegated view
    [controller.navigationController popViewControllerAnimated:YES];    
}

Finally open MainStoryboard.storyboard then link the Save button to the save action.  Do this by holding down control and dragging a line from the Save button down to the yellow circle on the Role Detail Table View Controller.  You should get a pop-up on which you should select ‘save’:

Deleting Existing Data

Deleting is easy … too easy!  All you have to do is add the following method to RolesTVC.m:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
 
    if (editingStyle == UITableViewCellEditingStyleDelete) {
 
        [self.tableView beginUpdates]; // Avoid  NSInternalInconsistencyException
 
        // Delete the role object that was swiped
        Role *roleToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"Deleting (%@)", roleToDelete.name);
        [self.managedObjectContext deleteObject:roleToDelete];
        [self.managedObjectContext save:nil];
 
        // Delete the (now empty) row on the table
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self performFetch];
 
        [self.tableView endUpdates];
    }
}

Run the project and you should be able to edit and delete Roles.  (Swipe a row on the RolesTVC to delete that row.)

That’s it! Stay tuned for Part 4 where I’ll talk about getting some relationships into Core Data.

Here’s the complete source code so far

If you liked this tutorial or found something wrong with it please let me know!

If you want to support my work and have an iPad please consider purchasing iSoccer *wink*

-Tim

Go to Part 4 or the Tutorials Index


Be Sociable, Share!
     

    About Tim Roadley

    I'm a senior analytics software consultant at eMite Pty Ltd primarily focused on delivering business intelligence dashboards, currently for one of Australia’s major banks. I'm also working on a revamped version of eMite's iOS App for release under iOS 7. Prior to eMite, I was Infrastructure Manager at Cuscal Pty Ltd where I was heavily involved in designing and implementing a payments switch that drives 1300+ ATM’s Australia wide. I have several apps on the App Store, including Teamwork, iSoccer and now Grocery Dude and Grocery Cloud. In my down time I enjoy spending time with my wonderful wife Tracey and two lovely children Tyler and Taliah.
    71 Comments

    Posted by on February 14, 2012 in iOS Tutorials

     

    71 Responses to Core Data Basics Part 3 – Editing and Deleting

    1. adrian phillips

      February 15, 2012 at 12:57 am

      hi tim,

      excellent work as always brother. very easy to follow and very descriptive. two thumbs up.:)

      i have two questions though:

      1- how do you pre add data to the role detail table view through the sql or you hard code it in role detail view?

      2- when i run my project and try to add a row it does add it fine but the addition takes place from the third row and not the first. so when i add an entry it becomes row number three and the first two rows are empty. is it something i have done?

      thanks a million for taking the time to write this tutorial. pretty useful for guys like me.

      thanks

      adrian

       
    2. Adrian

      February 15, 2012 at 1:34 am

      Tim,

      Please ignore the second question. I was setting up my storyboard the wrong way. It works just fine. But I am still interested in the answer for the first question.

      Thanks

      Adrian

       
      • Tim Roadley

        February 15, 2012 at 7:44 am

        Hi Adrian,

        Great question, I will add a Part 5 to the tutorial for pre-loading data.

        In the mean time basically you have two options and your choice will be driven by how much data you need to preload. If you only have a small amount of data you can easily preload with code. If you have a large amount of data you need to ship a second ‘default data’ database and preload from that. You should do the preload immediately after the database file is created for the first time by the App Delegate. Again depending on how much data you’re loading you might want to throw up a ‘Loading Defaults’ progress bar so people don’t get interface lag during the initial load – or load on a separate thread.

        You can read more about preloading with default data here

        Hope this helps :)

         
    3. Peter Nicholls

      March 14, 2012 at 2:17 am

      Hi. I love your tutorial. But few things puzzle me.
      1) why don’t you use the same view for add and edit as in other tutorials etc.? Surely this is most economical?
      2) you should add a bit about what advantages we gain by adding the custom helper class.

      Thank you!

       
      • Tim Roadley

        March 14, 2012 at 9:01 pm

        1) Good point, I’ve started to write part 8 to clean some annoying things up. There will be no add role or add person view after part 8! Don’t forget I write these as a personal learning exercise, not because I know what I’m doing lol

        2) What do you mean by helper class? The tableview subclass or the core data tableview subclass?

         
    4. Peter Nicholls

      March 14, 2012 at 10:19 pm

      Well Tim, your doing great. Take ages don’t it?! So much to learn and practice. I get so frustrated by the books too sometimes. Errors, or not explaining stuff. Anyway, I meant the core data class from Stanford. I’m doing their calculator exercise ATM from fall 2011…

       
    5. Martin

      March 15, 2012 at 12:15 am

      Great work! I have a couple of questions, though:

      I can’t get the role role detail disclosure to work. That is, no disclosure button shows up, and nothing happens when I tap a role row. Any suggestions?

      You refer to RoleDetail.h/.m. I take it you mean RoleDetailsTVC.h/.m, right?!

      Anyhow, thank you a lot for your work! It’s right to the point without too much talk! Really great!

       
      • Tim Roadley

        March 17, 2012 at 6:55 pm

        Did you hold control and drag to the detail view to create the segue?

        Thanks for picking up that typo :)

         
    6. Bill Spivey

      March 15, 2012 at 9:18 am

      Tim, I’ve created a little database entity in one project, and in another project that defines and uses it exactly the same way. Yet the two projects appear to see two different databases. Aren’t they supposed to see the same one? Is there a setting I need to make?

       
      • Tim Roadley

        March 17, 2012 at 6:47 pm

        You can’t use the same database with two different projects as far as I’m aware, if that is what you mean. Even if you’re creating a database in one for the purpose of pre-loading data you still can’t. Check this note out from Apple (the FAQ titled How do I use my existing SQLite database with Core Data.

         
    7. darrell

      March 19, 2012 at 3:14 am

      Hey Tim. First off, love your tutorials…they are awesome!

      I am having a little trouble though. Just like Martin, I can’t seem to get the detail disclosure to work. I have deleted my push segue to the detail view and re-created it several times but control dragging but it just won’t fire the prepareForSegue method. What am I missing???

      Thanks!

       
      • Tim Roadley

        March 19, 2012 at 6:49 am

        Darrell,

        After you created the segue again did you also give it an identifier that matches the identifier in the prepareForSegue method?

        Cheers

         
        • darrell

          March 19, 2012 at 9:03 am

          Yes, I did. It just doesn’t make sense to me. The prepareForSegue method just won’t seem to fire when I select a row. I’m going to download your sample source to see if I can see anything that I’ve missed. Any other ideas?

          Thanks!

           
        • darrell

          March 19, 2012 at 9:12 am

          Woohoo! I got it! I compared your sample source to mine and found that I had messed up some of the properties of my TableView. So I can get to my detail view now but my selected data isn’t populating. Hopefully that will be easy to fix.

          Thanks again! Love these tutorials!

           
        • kevin

          December 29, 2012 at 2:39 pm

          Hi Tim,

          I have having the same problem. I am using Simulator 6.0. The prepareForSegue never gets called. I put an NSLog right at the top and nothing ever shows up. I have deleted, re-connected, renamed etc…

          Your source code for this project does this same thing, it can add and delete but, when you tap to edit, it highlights blue and does nothing.

          Any other suggestions?

          Thanks
          Kevin

           
        • kevin

          December 29, 2012 at 2:48 pm

          Never mind…

          I was hooking to the ‘push’ under Accessory Action instead of the Segue.

          Sorry, I feel silly now but, at least you didn’t spend any time on my mistake.

          Kevin

           
    8. Eduardo

      March 26, 2012 at 11:25 am

      Hi Tim, very nice tutorials, kudos to you!

      Just a small issue, my project ended with 2 warnings:

      Assigning to ‘id’ from incompatible type ‘RolesTVC *const __strong’
      Assigning to ‘id’ from incompatible type ‘RolesTVC *const __strong’

      The RolesTVC interface shouldn’t declare the implemented protocols?

      @interface RolesTVC : CoreDataTableViewController

      in RolesTVC.h removes the warnings.

      Thanks

       
      • Chen Lala

        October 22, 2012 at 1:14 am

        Dear Eduardo
        Final how do you save the problem?
        Thanks

         
      • Alex Zavatone

        September 6, 2013 at 12:53 am

        Your browser strips out the required protocols for the interface since they appear within greater than and less than signs. Tim typed in the correct code and your browser hides it! Add these protocols to the RolesTVC @interface and put them within the proper characters: AddRoleTVCDelegate, RoleDetailTVCDelegate

         
    9. Aleksandr

      April 2, 2012 at 7:27 am

      And I also had to remove protocol names from delegate property declarations in AddRole.h and RoleDetail.h to get rid of the warnings.

       
    10. LAOMUSIC ARTS

      April 4, 2012 at 8:08 pm

      At runtime, I have a funny behavior caused by the deleting behavior.
      I guess it´s just too hard to swipe with a mouse, I guess

       
      • Tim Roadley

        April 4, 2012 at 8:11 pm

        Oh ok. If you find something is wrong with any tutorials let me know :)

         
        • Alex Zavatone

          September 6, 2013 at 12:54 am

          In the code for RolesTVC.h, some browsers strip out the protocols between the greater than and less than signs.

          The @interface for RolesTVC.h needs to have the following within greater than and less than signs: AddRoleTVCDelegate, RoleDetailTVCDelegate

          @interface RolesTVC : CoreDataTableViewController –put them in here–

          This also happens in all your exercises where you need a protocol. Thanks Safari!

           
      • Christina

        April 7, 2012 at 8:33 am

        Can u run it on your device? (you need a developer account for it)

         
    11. Jeffrey Kranenburg

      April 10, 2012 at 9:54 am

      Hi Tim,

      Awesome tutorial, you should write them for Apple Dev Center, at least I understand your stuff:-)

      Any change you could write a comment, on how to set the initial view controller as a normal UIViewController with Buttons, rather than starting of with a UITableView Controller?

      Then I could add like a little menu to that.
      If the UIViewController is embedded as in a UINavigationController that would be really sweet:-)

      Cheers Jeff

       
    12. Renato

      April 18, 2012 at 5:55 am

      On this step:

      Add/edit the following lines to the appropriate area in RolesTVC.h:

      I think you forgot adding to the quoted code:

      @interface RolesTableViewController : CoreDataTableViewController

      The delegates declaration.

       
    13. Edwin

      April 20, 2012 at 8:38 am

      I see there is some confusion about the interface line in RolesTVC.h

      @interface RolesTVC : CoreDataTableViewController

      The last part doesn’t get shown because of html-parsing.
      Just add “AddRoleTVCDelegate, RoleDetailTVCDelegate” to this (replace the quotes by less-than/greater-than brackets).

       
    14. Tim Roadley

      April 20, 2012 at 9:30 am

      I hate how the < and > signs get stripped by wordpress!!!!

       
      • Alex Zavatone

        September 6, 2013 at 3:39 am

        Yep. They are also pulled from RoleDetailTCV.h, which causes the app to crash when changing a value.

         
    15. Michael

      April 24, 2012 at 12:13 pm

      2 warnings if you edit RolesTVC.h this way, you need to add to the import line, which makes the code snippet to go into RolesTVC.h:

      #import “RoleDetailTVC.h” // so this class can be an RoleDetailTVCDelegate
      @interface RolesTVC : CoreDataTableViewController
      @property (strong, nonatomic) Role *selectedRole;

       
    16. Michael

      April 24, 2012 at 12:15 pm

      Woops, seems this is already adressed, delete my post.

       
    17. Al Schmeer

      April 27, 2012 at 4:31 am

      Tim,
      You’ve really helped me out to understand alot!

      I’m stuck on this part… I’m trying to understand how exactly you initiate the editing. I can add and delete with no problems. Swiping brings up the delete button.

      But what/how to you get it to edit when the app is running?

       
      • Al Schmeer

        April 27, 2012 at 4:49 am

        EDIT: I’m running this via the simulator…

         
    18. Amanda Mays

      May 3, 2012 at 4:28 am

      I changed the name of your file RolesDetailTVC to WFEditTopTVC in my project.

      I keep getting this error

      ARC Issue – No visible interface for “Top” declares the selector setName:

      at this line of code:
      [self.top setName:topNameTextField.text];

      Any ideas?

      This is the .m file.

      #import “WFEditTopTVC.h”

      @implementation WFEditTopTVC
      @synthesize delegate;
      @synthesize topNameTextField;
      @synthesize managedObjectContext = __managedObjectContext;
      @synthesize top = _top;

      - (void)viewDidLoad
      {
      NSLog(@”Setting the value of fields in this static table to that of the passed Role”);
      self.topNameTextField.text = self.top.topName;
      [super viewDidLoad];
      }

      - (void)viewDidUnload
      {
      [self setTopNameTextField:nil];
      [super viewDidUnload];
      }

      - (IBAction)save:(id)sender
      {
      NSLog(@”Telling the WFAddViewController Delegate that Save was tapped on the WFEditTopTVC”);
      [self.top setName:topNameTextField.text];
      [self.managedObjectContext save:nil]; // write to database
      [self.delegate theSaveButtonOnTheWFEditTopTVCWasTapped:self];
      }
      @end

       
      • Al Schmeer

        May 4, 2012 at 1:32 am

        Amanda,
        What does your TOP .h & .m files look like?

        You have the import of TOP in the WFEditTOPTVC.h file?

        I’m just starting myself…

         
        • Amanda Mays

          May 4, 2012 at 1:37 pm

          Also, what is causing this? I am running iOS 5.1 on Xcode 4.3 and using Storyboards.

          ‘NSInvalidArgumentException’, reason: ‘-[WFTopTableViewController topViewController]: unrecognized selector sent to instance 0x6d56f80′

          (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
          // Initial view controller is a Table View Controller, so we look up the window’s rootViewController. UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController; // Set up the controller. WFTopTableViewController *controller = (WFTopTableViewController *)navigationController.topViewController; // Pass the controller the managed object context for the first time. controller.managedObjectContext = self.managedObjectContext; return YES; }

           
      • Amanda Mays

        May 4, 2012 at 1:32 pm

        Here is the code for the Top.h and Top.m files you requested.

        #import
        #import

        @interface Top : NSManagedObject

        @property (nonatomic, retain) NSString * topDefinition;
        @property (nonatomic, retain) NSString * topName;
        @property (nonatomic, retain) NSString * topSecName;
        @property (nonatomic, retain) NSNumber * topViewPosition;
        @property (nonatomic, retain) NSSet *bottoms;
        @end

        @interface Top (CoreDataGeneratedAccessors)

        - (void)addBottomsObject:(NSManagedObject *)value;
        - (void)removeBottomsObject:(NSManagedObject *)value;
        - (void)addBottoms:(NSSet *)values;
        - (void)removeBottoms:(NSSet *)values;

        @end

        #import “Top.h”

        @implementation Top

        @dynamic topDefinition;
        @dynamic topName;
        @dynamic topSecName;
        @dynamic topViewPosition;
        @dynamic bottoms;

        @end

         
        • Al Schmeer

          May 5, 2012 at 12:28 am

          Amanda,

          Change topName in the Top .h & .m files to name.
          If I remember correctly, using property and dynamic autocreates the access methods. So for instance, if you have it set to “name”, it will create the setName method. Auto makes the small “s” of set and capital “N” on name, all based off the “name”.

          You used the setName method ( [self.top setName:topNameTextField.text]; ), but it doesn’t exist because you used the name topName.

          If you keep the topName in the Top .h & .m files, you’ll need to change the use of the setName method to the correct one… which I “think” might be: setTopName

          Again, I’m very new to this… please let me know if that helped! Also, I’m not the author of these series.

           
        • Amanda Mays

          May 8, 2012 at 1:00 am

          Thanks for your help. I appreciate it.

           
    19. MIchael

      May 5, 2012 at 1:29 pm

      Hey Tim,

      First of all, awesome tutorial! This core data series has been so helpful.

      I have one question. Is there a way to change the Push segue to a Modal segue when you tap the “+” button on the Navigation Bar? I tried to change it manually through the storyboard and add a new navigation bar manually. Now, when I add the buttons and link everything up, the “save” button doesn’t work.

      Any Ideas? Thanks a ton!

       
    20. Al Schmeer

      May 5, 2012 at 11:39 pm

      I figured out what I was doing wrong… I had the segue going from the whole Role tableview instead on the cell.
      Working completely now.

      Wanted to thank you again for this tutorial, it really has helped me tremendously!!!

       
    21. Jon Brown

      June 8, 2012 at 8:03 am

      I need help!!! I have followed your tutorial and subclassed a Table View Controller however when I run my app I get the following errors

      2012-06-07 17:52:14.445 Seafood Guide[7951:fb03] Setting up a Fetched Results Controller for the Entity named Seafood
      2012-06-07 17:52:14.470 Seafood Guide[7951:fb03] There’s stuff in the database so skipping the import of default data
      2012-06-07 17:52:16.178 Seafood Guide[7951:fb03] Setting up a Fetched Results Controller for the Entity named Seafood
      2012-06-07 17:52:16.179 Seafood Guide[7951:fb03] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext’
      *** First throw call stack:
      (0x15a9022 0x1b61cd6 0x11cef39 0×28613 0x286e9 0x2d238f 0x2d25eb 0x2d2893 0x2e2ff1 0x2e385f 0x2e3e06 0x2e3a24 0x63fde6 0x6344d0 0x2d15ab 0x9b51 0x129b0 0x13c46 0xb2f85d 0x157d936 0x157d3d7 0x14e0790 0x14dfd84 0x14dfc9b 0x249b7d8 0x249b88a 0×209626 0x230d 0×2275)
      terminate called throwing an exception

      any ideas would be helpful. :) Love your site and thanks in advance!!

       
      • Jon Brown

        June 8, 2012 at 8:05 am

        Email me directly and I can send you my project file if it helps, thanks in advance.

         
      • Christina McCaig

        December 6, 2012 at 5:31 am

        Did you find a fix for this?

         
      • Chen Lala

        April 20, 2013 at 1:59 am

        I have the same problem as bellow :2013-04-19 23:26:20.056 dsdd[7609:c07] Setting up a Fetched Results Controller for the Entity named Role
        2013-04-19 23:26:20.058 dsdd[7609:c07] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext’
        *** First throw call stack:
        (0x16a9012 0x14cee7e 0×158115 0xc2f3 0xc3f9 0x4f6103 0x4f642b 0x503f80 0x50bfad 0x50c89b 0x50ce93 0x50ca88 0x868e63 0x85ab99 0x85ac14 0x14e2705 0x4162c0 0x652a64 0x14e2705 0x4162c0 0×416258 0x4d7021 0x4d757f 0x4d66e8 0x445cef 0x445f02 0x423d4a 0×415698 0x2424df9 0x2424ad0 0x161ebf5 0x161e962 0x164fbb6 0x164ef44 0x164ee1b 0x24237e3 0×2423668 0x412ffc 0x230d 0×2235)
        libc++abi.dylib: terminate called throwing an exception
        (lldb)
        @@ Can you tell me how to solve it?

         
    22. Ken Fogel

      July 19, 2012 at 3:52 am

      Great tutorial! I had one small problem in that the edit feature would not work in the simulator. But when I ran it on the phone it worked.

       
    23. Fred

      July 21, 2012 at 5:12 pm

      Thank’s a lot Tim !
      Very very good job !
      But I have this issue when I “save” in the addRoleTVC: ”

      Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘+entityForName: could not locate an NSManagedObjectModel for entity name ‘Role”

      I downloaded your project who works fine, but in mine working on iPad project with other names(not Role for me) I really don’t find where is my pb.
      Thank you again
      Fred

       
    24. Angga

      July 24, 2012 at 3:46 pm

      thank’s for this tutorial..

      i need help..
      How to delete a object in coredata & cell without edit fuction?

       
      • Howard

        October 4, 2012 at 8:20 am

        Angga,

        To delete a row simply ‘swipe’ and the delete button should pop up!

        HP

         
    25. alejander

      July 29, 2012 at 8:07 am

      Thanks for this tutorial… you forget set the protocols in the RolesTVC interface declaration, this causes two advertaisments in the prepareForSegue.
      In the source code is correct, but not in the tutorial.

      Thanks for your work. Alex.

       
    26. Sean

      August 9, 2012 at 6:20 pm

      Hi Tim,
      Thanks very much for your tutorial. It helped me a lot. It’s really great one for the beginners.
      I believe I did my whole job followed your tutial,however, I always got same problem shown following:

      2012-08-09 16:12:47.666 CandsProject[1810:fb03] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 2 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).’

      I serched a lot solution from internet, but did not get the right one. Do you have any idea about it? Any suggestion will be appriciated.

      Regards,
      Sean

       
    27. Sean

      August 9, 2012 at 6:40 pm

      Hi Tim,
      I have got the solution from the Internet. Good job any way.
      Best Regrads,
      Sean.

       
      • Josh

        August 15, 2012 at 2:54 am

        What was your solution?

         
      • MJ

        August 21, 2012 at 9:41 am

        Hi Sean,

        I have hit the same problem. Any chance you could share your solution?

        Thanks,

         
        • GJ

          August 29, 2012 at 5:18 am

          I experienced the same problem. It looks like in the sample code the CoreDataTableViewController file has a routine didChangeObject which does self.tableView deleteRowsAtIndexPaths: if suspendAutomaticTrackingOfChangesInManagedObjectContext is set.

          It appears that somehow this switch is not set in the sample and so the deleteRowsAtIndexPaths is not done in didChangeObject.

          Other weirdness: when I swipe to delete the NSFetchedResultsControllerDelegate routine controllerWillChangeContent is being called in my code (in the commitEditingStyle routine when the db is saved with [self.managedObjectContext save:nil]; but this does’t happen in the sample I downloaded.

          I’m stumped on why this is happening, maybe somebody has an idea as we seem to be travelling down the same wrong path?

           
        • GJ

          August 30, 2012 at 1:33 am

          OK, I figured out the “invalid number of rows” delete problem. In my RolesTVC.m file the line

          @synthesize fetchedResultsController = __fetchedResultsController;

          was missing. This didn’t flag as an error because the self.fetchedResultsController = assignment used
          – (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc
          which was in the coredatatableviewcontroller which RolesTVC inherited from.

          The setFetchedResultsController routine in coredatatableviewcontroller sets the delegate to self and that causes the NSFetchedResultsControllerDelegate routines like controllerWillChangeContent to be called.

          So, I think the tutorial code should not include the properties or synthesizes for fetchedResultsController and managedObjectContext, these should be inherited from the coredatatableviewcontroller versions.

          if you remove the @synthesize fetchedResultsController from the rolesTVC.m and change the commitEditingStyle like below, the program works with the coredatatableviewcontroller handling the table stuff for delete

          - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

          if (editingStyle == UITableViewCellEditingStyleDelete) {

          //[self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException

          // Delete the role object that was swiped
          Role *roleToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
          NSLog(@”Deleting (%@)”, roleToDelete.name);
          [self.managedObjectContext deleteObject:roleToDelete];
          [self.managedObjectContext save:nil];

          // Delete the (now empty) row on the table
          //[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
          //[self performFetch];

          //[self.tableView endUpdates];
          }
          }

           
      • Harshit Gupta

        January 31, 2013 at 8:18 pm

        whats the solution Sean… i am also facing the same problem

         
      • Harshit Gupta

        January 31, 2013 at 8:41 pm

        I followed the solution provided by Sean, which eventually solved my problem.

        You just need to comment out the following lines in “- (void)tableView: commitEditingStyle: forRowAtIndexPath: ” method:

        1. [self.tableView beginUpdates];
        2. [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        3. [self performFetch];
        4. [self.tableView endUpdates];

        Thanks Sean.

        This is the best tutorial i found ever on core data.

        Thanks a lot TIM.

         
    28. Howard

      October 4, 2012 at 8:17 am

      HP

      CG, you are correct in your solution and I agree, ” …the properties and synthesizes for fetchedResultsController and managedObjectContext, should be inherited from the coredatatableviewcontroller versions.”

      So, removing the properties and synthesizers…from the inherited files is the first step.

      The second step (after reading the comments from the CoreDataViewController.h

      ================

      // Turn this on before making any changes in the managed object context that
      // are a one-for-one result of the user manipulating rows directly in the table view.
      // Such changes cause the context to report them (after a brief delay),
      // and normally our fetchedResultsController would then try to update the table,
      // but that is unnecessary because the changes were made in the table already (by the user)
      // so the fetchedResultsController has nothing to do and needs to ignore those reports.
      // Turn this back off after the user has finished the change.
      // Note that the effect of setting this to NO actually gets delayed slightly
      // so as to ignore previously-posted, but not-yet-processed context-changed notifications,
      // therefore it is fine to set this to YES at the beginning of, e.g., tableView:moveRowAtIndexPath:toIndexPath:,
      // and then set it back to NO at the end of your implementation of that method.
      // It is not necessary (in fact, not desirable) to set this during row deletion or insertion
      // (but definitely for row moves).

      ============

      …if I read it correctly…) is to “turn this on” i.,e

      self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES

      at the beginning of the commitEditingStyle method and then at the end of the method, “…Turn this back off…”

      Doing steps 1 and 2 resolved the problem for me!

      if (editingStyle == UITableViewCellEditingStyleDelete) {

      self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
      [self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException

      // Delete the role object that was swiped
      Role *roleToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
      NSLog(@”Deleting (%@)”, roleToDelete.name);
      [self.managedObjectContext deleteObject:roleToDelete];
      [self save];

      // Delete the (now empty) row on the table
      [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
      [self performFetch];

      [self.tableView endUpdates];
      self.suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;

       
    29. Ahmad

      November 22, 2012 at 10:39 pm

      Very Nice
      Thank you dear

       
    30. Silvia

      November 23, 2012 at 3:59 am

      I’m missing it… where is the edit-button?

       
    31. propilotapps

      December 30, 2012 at 11:36 am

      Nice tutorial. I am trying to use sections in my table with, “sectionNameKeyPath:@”body””. It works great. However, when I try to delete the app would randomly crash with the following error – *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:1054 and a breakpoint in the commitEditingStyle: method after self.tableview endUpdates. Please help! Thank you

       
    32. surpher

      February 4, 2013 at 6:37 am

      Anyone figured out how to delete the last row in a section? I can’t seem to figure it out. It seems as if the number of sections is not updated and my app crashes every time the last row is to be deleted from a section in tableview.

      reason: ‘Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number f sections inserted or deleted (0 inserted, 0 deleted).’

       
    33. Propilotapps

      February 4, 2013 at 8:23 am

      Thanks for the help. I have found a workaround and will try out your suggestion as well. The workaround is very basic – I removed the delete feature from the first table view and added a button to the role detail view that deletes the specific role object. It works great, except the user has to go to the actual Role Detail view to delete an entry…hope this makes sense.

       
    34. Alex Zavatone

      September 6, 2013 at 12:32 am

      In the code for RolesTVC.h, some browsers strip out the protocols between the greater than and less than signs.

      The @interface for RolesTVC.h needs to have the following within greater than and less than signs: AddRoleTVCDelegate, RoleDetailTVCDelegate

      @interface RolesTVC : CoreDataTableViewController –put them in here–

       
    35. Alex Zavatone

      September 6, 2013 at 3:37 am

      RoleDetailTVC.h needs an NSObject protocol at the end of @protocol line or changing a value will trigger the abort()

      This is another area where a protocol within special characters is stripped out of the code that Tim typed by many browsers.

       
    36. Mark

      November 24, 2013 at 6:48 am

      Great tutorial Tim!
      It’s getting me up to speed with Core Data and with Storyboards.

       
    37. Narumol Pugkhem

      May 13, 2014 at 6:39 am

      I love you tutorial, I was searching for Coredata with multiple entities and found this tutorial so I decided to follow along the whole tutorial. Very easy to follow and helps me understand using fetchedResultsController with TableViewController. No longer mystery ! Only found one mistake, might have been the browser’s !

      #import “RoleDetailTVC.h” // so this class can be an RoleDetailTVCDelegate
      @interface RolesTVC : CoreDataTableViewController
      @property (strong, nonatomic) Role *selectedRole;

      change the @interface line to

      @interface RolesTVC : CoreDataTableViewController

       
    38. Inderdeep Singh

      July 8, 2014 at 10:28 am

      Great Tutorial .. thank You !!

       

    Leave a Reply