RSS

Learning Core Data for iOS

As you progress through the chapters of Learning Core Data for iOS, you’ll build a fully functional Core Data App from scratch. Each key piece of information will be explained in succinct detail so you can apply what you’ve learned straight away. The sample application built throughout this book has been especially designed to demonstrate as many aspects of Core Data as possible. At the same time it is a completely real-world application available on the App Store today. This should make it easier to absorb concepts as you relate them to real-life scenarios.

The arrival of iOS 7 has seen major improvements in the speed, reliability, and simplicity of Core Data integration with iCloud. I encourage anyone who has previously given up on this technology to give it another go, because you will be pleasantly surprised.

Scroll to the bottom of this page for the complete source code!

Chapter Outline

  • Chapter 1, “Your First Core Data Application”—The groundwork is laid as the fundamental concepts of Core Data are introduced. You’ll be shown what Core Data is, and just as importantly what it isn’t. The first helper class CoreDataHelper is created as Core Data integration with an existing application is demonstrated with Grocery Dude.
  • Chapter 2, “Managed Object Model Basics”—Data models are introduced as parallels are drawn between traditional database schema design and Core Data. You’ll be shown how to configure a basic managed object model as entities and attributes are discussed, along with accompanying advice on choosing the right data types. Inserting, fetching, filtering, sorting and deleting managed objects is also covered and followed up with an introduction to fetch request templates.
  • Chapter 3, “Managed Object Model Migration”—Experience lightweight migration, default migration, and using a migration manager to display migration progress. Learn how to make an informed decision when deciding between migration options for your own applications and become comfortable with the model versioning capabilities of Core Data.
  • Chapter 4, “Managed Object Model Expansion”—The true power of a relational data model is unlocked as different types of relationships are explained and added to Grocery Dude. Other model features such as abstract and parent entities are also covered, along with techniques for dealing with data validation errors.
  • Chapter 5, “Table Views”—The application really comes to life as Core Data is used to drive memory efficient and highly performing table-views using a fetched results controller. Of course, most of the generic legwork is put into a reusable table-view controller subclass called CoreDataTVC. By dropping this class into your own applications, you can easily deploy Core Data driven table-views yourself.
  • Chapter 6, “Views”—Working with managed objects takes a front seat as you’re shown how to pass them around the application. Objects selected on a table-view are passed to a second view ready for editing. The editing interface is added to Grocery Dude demonstrating how to work with objects and then save them back to the persistent store.
  • Chapter 7, “Picker Views”—As a nice touch, Core Data driven picker-views are added to the editing views. Picker-views allow the user to quickly assign existing items to a unit of measurement, home location or shop location. A special reusable text-field subclass called CoreDataPickerTF is introduced, which replaces the keyboard with a Core Data picker-view whenever an associated text-field is tapped.
  • Chapter 8, “Pre-loading Data”—Techniques for generating a persistent store full of default data from XML are explained and demonstrated in this chapter as the generic CoreDataImporter helper class is introduced. Once you have a persistent store to include with a shipping application, you’ll then be shown how to determine whether a default data import is required or even desired by the user.
  • Chapter 9, “Deep Copy”—A highly flexible and fine-grained alternative to migratePersistentStore, deep copy, allows you to copy objects and relationships from selected entities between persistent stores. In this chapter, the CoreDataImporter helper class is enhanced with the deep copy capability.
  • Chapter 10, “Performance”—Gain experience with Instruments as you identify and eliminate performance issues caused by the common pitfalls of a Core Data application. The camera functionality is introduced to highlight these issues and demonstrates just how important good model design is to a well performing application.
  • Chapter 11, “Background Processing”—Top-notch performance requires intensive tasks be offloaded to a background thread. Learn just how easy it is to run processes in the background as the example of photo thumbnail generation is added with the new generic helper class called Thumbnailer. Also learn how to keep memory usage low with another helper class, called Faulter.
  • Chapter 12, “Search”—Learn how to handle twin fetched results controllers in the one table-view as you implement efficient search in CoreDataTVC.
  • Chapter 13, “Backup and Restore”—Create backups and synchronize them to Dropbox using their Sync API. Restore data to any device using the same Dropbox account at the touch of a button.
  • Chapter 14, “iCloud”—Enjoy the easiest, most reliable Core Data integration with iCloud yet. Handle multiple accounts and varying preferences on using iCloud without missing a beat.
  • Chapter 15, “Taming iCloud”—Take iCloud integration to the next level with entity level seeding and unique object de-duplication. Accurately emulate first time iCloud use by resetting ubiquitous content globally, the right way.
  • Chapter 16, “Web Service Integration”—Enable collaboration as cross-platform data sharing between multiple users is introduced with StackMob. StackMob have one of the best free Backend-as-a-Service (BaaS) offerings available, and their iOS API is native to Core Data.

All Source Code

LearningCoreDataForiOS_AllSourceCode.zip

Source Code By Chapter

Chapter Source Code
Appendix A – Preparing Grocery Dude for Chapter 1 GroceryDude-AfterAppendixA.zip
Chapter 1 – Your First Core Data Application GroceryDude-AfterChapter01.zip
Chapter 2 – Managed Object Model Basics GroceryDude-AfterChapter02.zip
Chapter 3 – Managed Object Model Migration GroceryDude-AfterChapter03.zip
Chapter 4 – Managed Object Model Expansion GroceryDude-AfterChapter04.zip
Chapter 5 – Table Views GroceryDude-AfterChapter05.zip
Chapter 6 – Views GroceryDude-AfterChapter06.zip
Chapter 7 – Picker Views GroceryDude-AfterChapter07.zip
Chapter 8 – Pre-loading Data GroceryDude-AfterChapter08.zip
Chapter 9 – Deep Copy GroceryDude-AfterChapter09.zip
Chapter 10 – Performance GroceryDude-AfterChapter10.zip
Chapter 11 – Background Processing GroceryDude-AfterChapter11.zip
Chapter 12 – Search GroceryDude-AfterChapter12.zip
Chapter 13 – Backup and Restore GroceryDude-AfterChapter13.zip
Chapter 14 – iCloud GroceryDude-AfterChapter14.zip
Chapter 15 – Taming iCloud GroceryDude-AfterChapter15.zip
Chapter 15 – Easy iCloud EasyiCloud.zip
Chapter 15 – Generic Core Data Classes Generic Core Data Classes.zip … Please read CoreDataHelper.h for usage instructions
Appendix B – Preparing Grocery Cloud for Chapter 16 GroceryCloud-AfterAppendixB.zip
Chapter 16 – Web Service Integration GroceryCloud-AfterChapter16.zip
Be Sociable, Share!
     

    164 Responses to Learning Core Data for iOS

    1. Tim Roadley

      February 24, 2014 at 4:27 pm

      @Tom .. glad it’s working for you now :)

       
    2. lenny

      February 25, 2014 at 3:52 pm

      Any plans to write about Dropbox Data Store / iCloud and Core Data?

       
      • Tim Roadley

        February 25, 2014 at 3:59 pm

        Hmm not at this stage, I’m working on a new version of Teamwork. It’s a shame that dropbox added that functionality when my book was almost finished :(

         
    3. Koen

      March 5, 2014 at 10:32 pm

      This book is amazing. I have “The other CoreData book”, but never really grasped it. So I started using MagicalRecord to hide all the CoreData stuff, and focus on my own app, but I recently needed to dig deeper for a migration problem in my app. While searching for a solution I stumbled on your sample chapter on migration, and liked it so much that I immediately bought the book. So far it has been great, I finally feel I am understanding Core Data.

       
      • Tim Roadley

        March 6, 2014 at 7:20 am

        Thanks for your kind feedback, glad it’s helped!

         
    4. Joe

      March 8, 2014 at 1:38 am

      Tim,
      Your tutorials and book are by far the best! Learning CoreData was a big learning curve for me even though I have over 25 years of experience as I kept approaching it with traditional database thinking. The tutorials by Apple are not very intuitive and your explanations easily got me past all my false starts! I do still have one hang up with pursuing iCloud syncing. I have a very large .sqlite db that I need to seed and not all of the tables have unique attributes resulting in non-unique attribute errors during the deep copy. Plus the deep copy takes several minutes due to the large volume of data. Isn’t there an easy way to copy an initial seed database without having to do a deep copy, or am I overlooking the obvious?
      In either case, thanks again for the great work. I now have a successful app with 10’s of thousands of users!

       
      • Tim Roadley

        March 8, 2014 at 8:40 am

        Hi Joe,

        I’m glad the tutorials & book have been useful! If you have a really large data set which should all be in iCloud, consider using a variation of Listing 9.19 (migratePersistentStore) to get your data into iCloud. That said, if not all of the data belongs in iCloud (i.e. it’s static data), I would recommend using ‘configurations’ to separate your data and put large static data locally and only stuff that should be in iCloud in iCloud. Page 369 touches on configurations although doesn’t demonstrate their use fully.

        Let me know how this goes!

        Cheers,

        Tim

         
    5. Koen

      March 9, 2014 at 6:32 am

      I made a lot of progress in the book, but there is one thing I don’t understand yet. When I disable MagicalRecord, and use CoreDataHelper instead to load my data, I see an empty tableView. Both MR and CDH are accessing the same store, so I am confused. If I then turn MR back on, and disable CDH, everything looks again as expected. Do I need to use a Deep Copy to get the entities that were created with MR, or am I missing something else?

       
      • Koen

        March 10, 2014 at 12:19 am

        Hmm, it looks like MR stores the sqlite file in a different location than where CDH looks:

        MR:
        /Users/koen/Library/Application Support/iPhone Simulator/7.1/Applications/A302C253-9B86-4350-8C93-FF7805552AE0/Library/Application Support/InDigestion/InDigestion.sqlite

        CDH:
        /Users/koen/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/A302C253-9B86-4350-8C93-FF7805552AE0/Documents/Stores/InDigestion.sqlite)

        I changed the code in CDH to go look into the MR defined folder and it’s all working now.

         
    6. Miguel

      March 9, 2014 at 12:39 pm

      Tim i bought your book and i’m currently on chapter 4. Great book by the way. I have a burning question that i hope you can answer. I’m creating an application that would have a file with approximately 10 to 15 thousand records. I like to pre-populate the data before submission to the app store. However when i follow your book (thus far) i don’t see how i can have the DB in my project. in other words i have to go to ~/users/myUserName/Library/Application Support/iPhone/Simulator/ but i would imagine that i would have to move this file to the project directory prior to submitting to the app store. Any advice on how to do this? I would love to get an answer.
      Thanks
      Miguel

       
      • Miguel

        March 14, 2014 at 6:21 am

        I figured it out Tim. Thanks anyways.

         
    7. Nigel Hamilton

      March 13, 2014 at 6:58 am

      Hi Tim,
      I bought your book as I need to add iCloud support to an existing app. I was really most interested in the last couple of chapters, but thought I should go through the whole book so that I could change my Core Data stack to be the same as yours, before trying to implement the iCloud functionality.
      I have to say this is probably the best iOS book that I have read. The instructions are so clear that I have successfully made all of the changes and ran the code, getting the correct results – until I came to chapter 15! Before describing where it is going wrong, I must say that I have never gone through a book trying all of the examples, and had such success as with this one. Often it is my mistake, but equally the books I have read have had errors e.g. code in book different from the code you can download.
      Anyway, with your book, all went really well until I got to chapter 15 and added the Deduplicator functionality. Then when I run it, it just crashes. So far, I had been running everything on the simulator. I tried deleting the app from the simulator, doing a Clean etc. but it crashes every time. Eventually, I tried running on my iPhone, and it seems to run fine.
      I will copy some of the Console log below. Have you any suggestions on how I could debug (and fix) this?
      Thanks again for a superb book.

      2014-03-12 20:46:13.947 Grocery Dude[44053:70b] Running CoreDataHelper ‘init’
      2014-03-12 20:46:13.987 Grocery Dude[44053:70b] Running CoreDataHelper ‘listenForStoreChanges’
      2014-03-12 20:46:14.056 Grocery Dude[44053:70b] Running CoreDataHelper ‘setupCoreData’
      2014-03-12 20:46:14.057 Grocery Dude[44053:70b] Running CoreDataHelper ‘iCloudEnabledByUser’
      2014-03-12 20:46:14.058 Grocery Dude[44053:70b] ** iCloud is DISABLED in Settings **
      2014-03-12 20:46:14.059 Grocery Dude[44053:70b] ** Attempting to load the Local, Non-iCloud Store **
      2014-03-12 20:46:14.060 Grocery Dude[44053:70b] Running CoreDataHelper ‘setDefaultDataStoreAsInitialStore’
      2014-03-12 20:46:14.061 Grocery Dude[44053:70b] Running CoreDataHelper ‘storeURL’
      2014-03-12 20:46:14.061 Grocery Dude[44053:70b] Running CoreDataHelper ‘applicationStoresDirectory’
      2014-03-12 20:46:14.062 Grocery Dude[44053:70b] Running CoreDataHelper ‘applicationDocumentsDirectory’
      2014-03-12 20:46:14.073 Grocery Dude[44053:70b] Running CoreDataHelper ‘loadStore’
      2014-03-12 20:46:14.074 Grocery Dude[44053:70b] Running CoreDataHelper ‘storeURL’
      2014-03-12 20:46:14.074 Grocery Dude[44053:70b] Running CoreDataHelper ‘applicationStoresDirectory’
      2014-03-12 20:46:14.075 Grocery Dude[44053:70b] Running CoreDataHelper ‘applicationDocumentsDirectory’
      2014-03-12 20:46:14.093 Grocery Dude[44053:70b] CoreData: annotation: Connecting to sqlite database file at “/Users/nigelhamilton/Library/Application Support/iPhone Simulator/7.1/Applications/73E60861-9DCE-4D70-854D-189669AEC148/Documents/Stores/Grocery-Dude.sqlite”
      2014-03-12 20:46:14.515 Grocery Dude[44053:70b] CoreData: sql: pragma journal_mode=wal
      2014-03-12 20:46:14.516 Grocery Dude[44053:70b] CoreData: sql: pragma cache_size=200
      2014-03-12 20:46:14.517 Grocery Dude[44053:70b] CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
      2014-03-12 20:46:14.821 Grocery Dude[44053:70b] CoreData: annotation: Disconnecting from sqlite database.
      2014-03-12 20:46:14.842 Grocery Dude[44053:70b] FAILED to add store, Error: Error Domain=NSCocoaErrorDomain Code=134130 “The operation couldn’t be completed. (Cocoa error 134130.)” UserInfo=0x8fcecb0 {URL=file:///Users/nigelhamilton/Library/Application%20Support/iPhone%20Simulator/7.1/Applications/73E60861-9DCE-4D70-854D-189669AEC148/Documents/Stores/Grocery-Dude.sqlite, metadata={
      DefaultDataImported = 1;
      NSPersistenceFrameworkVersion = 478;
      NSStoreModelVersionHashes = {
      Item = ;
      “Item_Photo” = ;
      Location = ;
      LocationAtHome = ;
      LocationAtShop = ;
      Unit = ;
      };
      NSStoreModelVersionHashesVersion = 3;
      NSStoreModelVersionIdentifiers = (
      “”
      );
      NSStoreType = SQLite;
      NSStoreUUID = “A816EA20-01A2-41D9-90FC-C74BE21E2457″;
      “_NSAutoVacuumLevel” = 2;
      }, reason=Can’t find model for source store}

       
      • Tim Roadley

        March 13, 2014 at 7:51 am

        Hi Nigel,

        Firstly, thanks for buying my book!

        Based on that error, it’s complaining that the model of the store you want to migrate isn’t compatible with the store you’re migrating to. This will happen you’re migrating between a model you created and a model I created. For example, if you’ve built the whole project from scratch and you’re using the default data store I supplied, then this could be the cause of your issue. If you’re not using any of my sample projects or files, double check that the version of the default data store you have in your project matches the model version you ship the app with.

        As a side note, please be aware of this errata with iCloud integration. There’s a slightly different setupCoreData required. http://timroadley.com/2014/02/13/learning-core-data-for-ios-errata/

        Let me know how this goes!

        Tim

         
    8. Nigel Hamilton

      March 13, 2014 at 5:12 pm

      Thanks for the reply Tim. I have been either entering the code myself or cutting and pasting from the downloaded code, all the way through. I have been creating the model myself, following your instructions, but obviously could have made a mistake. I compared the 2 models and couldn’t see a difference, but I’ll look again.
      If my model is wrong though, why would it run ok on my phone, but crash on the simulator?

       
      • Tim Roadley

        March 13, 2014 at 5:52 pm

        Hi Nigel,

        Did you generate your own DefaultData.sqlite? If you’ve upgraded the current model to a higher version than DefaultData.sqlite is at then that might explain the crash. It doesn’t explain why it’s working on the device and not the simulator. There must be a more recent version of the model on one of these devices.

        Page 220 eludes to this need for a newer file “Note that this means that if the model is upgraded in the future, you’ll need to ship a pre-upgraded version of DefaultData.sqlite with it.”

        To stop the crashing you could delete the app from the sim and run it again. If you don’t want to lose the app state on the sim then temporarily change the bundle identifier.

        Cheers,

        Tim

         
        • Nigel Hamilton

          March 14, 2014 at 6:02 am

          I have deleted the app from both simulator and iPhone but it always crashes on the simulator, but ok on the phone. Before I had tried it on the phone, I had downloaded the app itself from iTunes. That’s why I deleted the app and it’s data from the phone and tried again – still worked ok.
          I wondered about having the “wrong” default data when trying to get it to work on the simulator, so I deleted the default file and copied the one in the Chapter 14 source code – still no joy.

           
    9. Nigel Hamilton

      March 14, 2014 at 6:52 am

      I can’t see any difference between my model and the one in the source code. I have tried the defaultData.sqlite from chapters 14 and 15. This will probably be a stupid question, but on P220 when you talk about changing the model means having to ship a pre-upgraded version of DefaultData, does that mean ship a version of defaultData produced before the upgrade, or does it mean upgrade it (to match the model) pre sending it to the user? Where it is going wrong for me (on simulator but not iPhone??) is just after adding the “modified” attributes. Do I need a DefaultData with “modified” in it? The one with the source download does not have this, as far as I can see.

       
    10. Joe

      March 14, 2014 at 12:19 pm

      Hey Tim,
      As my teenage daughter would say OMG! I totally missed the last page of chapter 9 including the listing 9.19 that you directed me to! In either case, all is working fine except I am getting duplicate records. I run the app on an iPhone and iPad and get two copies of every record. However, the store is getting migrated to icloud and changes are syncing! I am soooo close! If you can put me in the right direction to utilize the existing icloud store after the first device migrates and not append an entire duplicate of the store when another device joins, I’d appreciate it!

       
    11. Nathan Furman

      March 18, 2014 at 6:08 am

      Hi Tim. Great book thanks. Just finished chapter 11. Thumbnail won’t pop up at all. Downloaded your source code. Same result.

       
    12. Nigel Hamilton

      March 18, 2014 at 6:58 am

      Hi Tim,
      I have gone through your excellent book up to page 366. The only problem I thought I’d seen so far was once I started the iCloud chapters, the app would crash on the simulator, but ok on iPhone and iPad (as reported earlier). I now wanted to check that I could sync from device to device. I tried running on my iPhone, with iCloud enabled, and adding an item, then checking if the item appeared on the iPad (also iCloud enabled – same account). This didn’t seem to work. I was about to restart the iCloud chapters, but decided instead to download the app from the app store (after deleting from both devices) and try again.
      It doesn’t seem to work for me. I was wondering if I it is actually supposed to be possible to sync between devices??
      If I disable iCloud, add an item, reenable iCloud, then the new item merges ok. But with both devices enabled for iCloud, adding an item to one device does not result in that item appearing on the other device. Should it?

       
      • Tim Roadley

        March 18, 2014 at 10:04 am

        Hi Nigel,

        It sounds like your iCloud container has become inconsistent. On page 367 there are ‘Developing with a Clean Slate’ instructions. Can you please try those out for me?

        Thanks!

         
    13. Nigel Hamilton

      March 18, 2014 at 5:28 pm

      Hi Tim,
      I had a quick try of this before going to work but it didn’t get as far as the return YES. I think there is something wrong with my store – I’ll look again tonight:
      2014-03-18 07:17:11.627 Grocery Dude[202:60b] Running CoreDataHelper ‘iCloudStoreURL’
      2014-03-18 07:17:11.629 Grocery Dude[202:60b] Running CoreDataHelper ‘applicationStoresDirectory’
      2014-03-18 07:17:11.631 Grocery Dude[202:60b] Running CoreDataHelper ‘applicationDocumentsDirectory’
      2014-03-18 07:17:11.714 Grocery Dude[202:60b] +[PFUbiquitySetupAssistant createActualStoreURLForStoreURL:localPeerID:containerIdentifier:andStoreName:](3833): CoreData: Ubiquity: Created actual store url: file:///var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/CoreDataUbiquitySupport/mobile~877ABCA4-9DCD-48E7-A008-A5F28A9A0B17/Grocery-Dude/D578A4CC-71BA-4453-92B0-1DF322BDA17C/store/iCloud.sqlite
      for url: file:///var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/iCloud.sqlite
      2014-03-18 07:17:11.716 Grocery Dude[202:60b] -[PFUbiquitySetupAssistant doPostValidationInit:](568): CoreData: Ubiquity:
      Store file exists: 1 – file:///var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/CoreDataUbiquitySupport/mobile~877ABCA4-9DCD-48E7-A008-A5F28A9A0B17/Grocery-Dude/D578A4CC-71BA-4453-92B0-1DF322BDA17C/store/iCloud.sqlite
      2014-03-18 07:17:11.718 Grocery Dude[202:60b] -[PFUbiquitySetupAssistant validateOptionsWithError:](528): CoreData: Ubiquity:
      options: {
      NSInferMappingModelAutomaticallyOption = 1;
      NSMigratePersistentStoresAutomaticallyOption = 1;
      NSPersistentStoreUbiquitousContentNameKey = “Grocery-Dude”;
      }
      psc:
      store: (null)
      storeURL: file:///var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/iCloud.sqlite
      actualStoreURL: file:///var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/CoreDataUbiquitySupport/mobile~877ABCA4-9DCD-48E7-A008-A5F28A9A0B17/Grocery-Dude/D578A4CC-71BA-4453-92B0-1DF322BDA17C/store/iCloud.sqlite
      storeMetadata: (null)
      storeKV: (null)
      storeFileExists: 1
      storeFileIsReadOnly: 0
      ubiquityEnabled: 1
      ubiquityIdentityToken:
      ubiquityRootURL: (null)
      ubiquityRootSubpath: (null)
      ubiquityName: Grocery-Dude
      ubiquityContainerIdentifier: (null)
      localPeerID: mobile~877ABCA4-9DCD-48E7-A008-A5F28A9A0B17
      modelVersionHash: uMw05VjBXtdzWtBOEfwLvniag9c5dee77uakX4aLGjo=
      ubiquityRootLocation: (null)
      localRootLocation: : /var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/CoreDataUbiquitySupport/mobile~877ABCA4-9DCD-48E7-A008-A5F28A9A0B17/Grocery-Dude/D578A4CC-71BA-4453-92B0-1DF322BDA17C/container
      metaKV: (null)
      baseline: (null)
      baselineFileExists: 0
      hasUploadingBaseline: 0
      monitorBaslineUploadAsync: 0
      didBaselineCopy: 0
      baselineKV: (null)
      hasStoreMetadataFile: 0
      hasStoreMetadataEntry: 0
      hasContainerUUID: 0
      hasContainerUUIDInStore: 0
      needsMetadataRecovery: 0
      localPeerReceipt: (null)
      receiptKV: (null)
      containerIdentifier: (null)
      preStoreContainerUUID: D578A4CC-71BA-4453-92B0-1DF322BDA17C
      usedExistingUUIDMapping: 1
      hasLocalTransactionLogs: 0
      votedOffIsland: 0
      reapUbiquitousLogs: 0
      respondToBaselineRoll: 0
      hasMigrationOptions: 1
      didMigrateBaseline: 0
      storeWasMigrated: 0
      replayLogsSynchronously: 0
      useLocalAccount: 0
      abortSetup: 0
      gotExportNotification: 0
      2014-03-18 07:17:11.725 Grocery Dude[202:60b] CoreData: annotation: Connecting to sqlite database file at “/var/mobile/Applications/5C70C119-738A-4175-B751-8651A921F168/Documents/Stores/CoreDataUbiquitySupport/mobile~877ABCA4-9DCD-48E7-A008-A5F28A9A0B17/Grocery-Dude/D578A4CC-71BA-4453-92B0-1DF322BDA17C/store/iCloud.sqlite”
      2014-03-18 07:17:11.728 Grocery Dude[202:60b] CoreData: sql: pragma journal_mode=delete
      2014-03-18 07:17:11.730 Grocery Dude[202:60b] CoreData: sql: pragma cache_size=200
      2014-03-18 07:17:11.731 Grocery Dude[202:60b] CoreData: sql: CREATE TABLE IF NOT EXISTS Y_UBMETA (Y_PK INTEGER PRIMARY KEY ASC, YPEERID VARCHAR UNIQUE, YTRANSACTIONNUMBER INTEGER)
      2014-03-18 07:17:11.733 Grocery Dude[202:60b] CoreData: sql: CREATE TABLE IF NOT EXISTS Y_UBRANGE (Y_PK INTEGER PRIMARY_KEY ASC, YPEERID VARCHAR, YENTITYNAME VARCHAR, YRANGESTART INTEGER, YRANGEEND INTEGER, YPEERSTART INTEGER, YPEEREND INTEGER)
      2014-03-18 07:17:11.734 Grocery Dude[202:60b] CoreData: sql: CREATE TABLE IF NOT EXISTS Y_UBKVS (Y_PK INTEGER PRIMARY KEY ASC, YKEY VARCHAR UNIQUE, YVALUE VARCHAR)
      2014-03-18 07:17:11.736 Grocery Dude[202:60b] CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
      2014-03-18 07:17:11.922 Grocery Dude[202:60b] CoreData: annotation: Disconnecting from sqlite database.

       
      • Tim Roadley

        March 21, 2014 at 8:40 am

        ubiquityIdentityToken:
        ubiquityRootURL: (null)
        ubiquityRootSubpath: (null)
        ubiquityName: Grocery-Dude
        ubiquityContainerIdentifier: (null)

        Those things suggest the device is not enabled for iCloud or not signed in or something else has gone screwy

         
    14. Eli Spiritweaver

      March 19, 2014 at 10:54 am

      Hi Tim,

      Your book is a great step forward from the Staff Manager tutorials!
      I seem to have run into a problem using iCloud.

      I have built an app following the model in your book and when installing the app on a device the following happens:

      When iCloud is enabled, all entered data is “iCloud Data”.
      When iCloud is disabled in settings, the “ICloud Data” disappears.
      Then all new data entered becomes “Local Data”.
      When iCloud is re-enabled, the “iCloud Data” reappears and the “Local Data disappears”, only to reappear later when iCloud is disabled again.

      The “iCloud Data” is never merged with the “Local Data”. They are completely separate. The user is left with an either/or scenario.

      When I create a Dropbox backup, it seems that the backup is either empty or restricted to the “Local Data”

      Is this how the Grocery Dude app was intended to work?
      Or have I done something wrong?

      Your help would be greatly appreciated.

      Many thanks,
      Eli

       
      • Nigel Hamilton

        March 20, 2014 at 5:21 pm

        Eli – did you ever get anywhere with this? I have gone through the book including the EasyiCloud part. Mostly when I run EasyiCloud it performs in the way you describe i.e. local and cloud data stay separate. I don’t think that this is supposed to be the way it works. Tim’s test instructions say:

        Run EasyiCloud
        Tap + to create a ‘local’ item
        Write down the guid of the new item
        Press the Home Button
        Open Settings > iCloud
        Ensure that an iCloud account is signed in
        Scroll down an Ensure that Documents and Data is On
        Open Settings > EasyiCloud
        Turn Enable iCloud On
        Press the Home Button
        Open Easy iCloud
        Tap Ok to the prompt notifying you that your preference on using iCloud has changed
        Tap Merge to merge the local data with iCloud
        You should see the local item guid you wrote down earlier appear in the table view.
        Tap + to create an ‘iCloud’ item
        Repeat this procedure on another device using the same iCloud account

        I think this worked for me with the first item, but not on future attempts.
        In my log I see:
        2014-03-20 07:12:55.957 EasyiCloud[889:3b0b] Created Test object with someValue ‘Test: 92244D20-058E-4815-8D3E-C808E202CF33′
        2014-03-20 07:12:55.961 EasyiCloud[889:3b0b] Test object with someValue value ‘Test: 92244D20-058E-4815-8D3E-C808E202CF33′ already exists
        2014-03-20 07:12:55.964 EasyiCloud[889:3b0b] Created Test object with someValue ‘Test: 6A74DB09-2182-43A2-BE37-396DC824B37C’
        2014-03-20 07:12:55.966 EasyiCloud[889:3b0b] Test object with someValue value ‘Test: 6A74DB09-2182-43A2-BE37-396DC824B37C’ already exists
        2014-03-20 07:12:55.970 EasyiCloud[889:3b0b] Created Test object with someValue ‘Test: 3CBA1683-C8CB-4E0B-9229-82F58027A2AA’
        2014-03-20 07:12:55.973 EasyiCloud[889:3b0b] Test object with someValue value ‘Test: 3CBA1683-C8CB-4E0B-9229-82F58027A2AA’ already exists
        2014-03-20 07:12:55.974 EasyiCloud[889:3b0b] *** FINISHED DEEP COPY FROM NON-ICLOUD STORE TO ICLOUD STORE ***
        2014-03-20 07:12:55.976 EasyiCloud[889:3b0b] *** REMOVING OLD NON-ICLOUD STORE ***

        The 3 objects in question are my local data. Looks like it tries to merge them but doesn’t succeed (thinks it has already merged them). They don’t show when iCloud is enabled.

         
    15. Eli Spiritweaver

      March 20, 2014 at 5:41 pm

      Hi NIgel,

      I have been toggling the iCloud on/off switch in Settings -> AppName -> icloudSwitch. I have managed at one stage to enter data when iCloud is on and to have the data saved to iCloud on my iPhone and then to have the iCloud data reappear on my iPad when it merges the first time with iCloud. (I haven’t tried using the iCloud Documents and Data switch – yet).

      I am testing it at the moment to see if when I enter new info on the iPad, it also appears on the iPhone.

      Unfortunately I changed something somewhere while trying to get it to work and now the iPhone refuses to talk to iCloud.

      Going through Tims’s book again, it seems that the user must chooses either to use iCloud or Dropbox, he can’t use both because the main iCloud datastore seems to be stored in iCloud and not on the device. The local iCloud store is only a partial data store and backing it up with Dropbox would be fruitless.

      I was under the impression that having iCloud and Dropbox together would allow one to use iCloud and then to keep Dropbox backups for possible data-loss disasters.

      What concerns me is that when iCloud is off, the data entered into the App does not seem to sync to iCloud when it is then turned on, it gets locked into the local datastore which becomes inaccessible to iCloud when iCloud is switched on.

      Regards,
      Eli

       
    16. Eli Spiritweaver

      March 21, 2014 at 8:11 am

      Hi again Nigel,

      I can now confirm that I have managed to get Tim’s iCloud code working perfectly when applied to one’s own app.

      The only disclaimer is that I could not get the CoreDataHelper.m file from EasyiCloud to work for me, but the CoreDataHelper.m file from GroceryDude does work – after it has been edited to apply to your specific App.

      I have not been able to find what part of the code in GroceryDude is different from the EasyiCloud code that makes the App work, but I simply could not get the EasyiCloud code to import non-iCloud data to iCloud.

      The app creates two iCloud settings toggle switches: one in Settings -> iCloud -> Documents and Data -> AppName and the other in Settings -> AppName.

      When you install the App on your device, the iCloud switch is “On” by default and the Settings switch is “Off” by default.

      When you toggle the Setting switch “On” the App connects to iCloud and imports the iCloud stored data (if you have any) otherwise you can start creating data on your App and it will be stored to iCloud and it will appear on your other devices very promptly.

      If you want to use your App without iCloud, you then toggle the iCloud (Documents and Data) switch “Off”.

      When you want to start using iCloud again, you just toggle the iCloud switch “On” and all your non-iCloud data is imported to iCloud.

      I still believe that it would be a great functionality to be able to offer the user a Dropbox backup option which will backup the iCloud data.

      Although Dropbox does backup the iCloud.sqlite file, when it is restored, iCloud does not seem to be able to see it and creates a new one from its own servers.
      I can foresee a difficulty if a user somehow corrupts his iCloud store and loses his data – he would be left pulling his hair out and probably blaming the App and not iCloud!

      But plaudits to Tim for all the work he put into his book to create a working implementation of core data and iCloud which he has been kind enough to share with all us newbies.

      Regards,
      Eli

       
      • Nigel Hamilton

        March 21, 2014 at 5:18 pm

        Hi Eli,
        That’s great that you have it working on your own app!
        I have had mixed results with EasyiCloud. Last night I didn’t seem to merge properly and said items it was about to create (as a copy of original) already existed. When I stepped through, I found a situation where it did an “if (existingObject)” where existingObject is a manage object, and it would treat this as YES when I could see existingObject was nil (I know that sounds wrong – just reporting what I saw!). I change the code a little, and then everything started to work well. I changed the code back to the original, and it continued to work well! In fact, it worked really well. Merges were fast, and data merged on my iPhone appeared on my iPad etc.
        In my tests, I don’t see a difference between the 2 ways of turning off iCloud. What do you see as the difference?
        I don’t think this works as I originally expected, but it is probably operating correctly. What I expected was as follows. You would create your list. If you went “local” (i.e. iCloud disabled), you would see the same list, which you could add to. Going Cloud, you would see the same list )and it would go to other devices). In stead, when you go from local to Cloud, the local data is merged and deleted from the local store. If you go local again, you have a blank list. Whilst not what I expected, and possibly not what I want for my own app, it makes sense I think if you want the app to be used be more than one person on the same device, each with their own iCloud account. Actually, that might be a good thing for my app – users could all keep their own list on the family iPad, for example.
        Best wishes,
        Nigel

         
    17. Paul

      March 23, 2014 at 10:06 pm

      Hi Tim,

      Congratulations on creating one of the best resources for CoreData. I was progressing well, but am stuck trying to insert multiple attributes into an entity when importing from XML.

      This is probably a simple fix and I’d highly appreciate your guidance.

      p207, Listing 8.14, step 3a;

      How do I insert a second (or third) attribute for the same from XML? Every method which I have tried leads to new rows being created which do not map to the same unique object.

      It works fine for the “first” attribute in any Entity, but not for any second or third attribute in the same Entity when I try to pull data from XML using your example method.

      Kind regards, Paul.

       
      • Tim Roadley

        March 24, 2014 at 7:48 am

        Hi Paul,

        Thanks for reading!

        Page 208, Listing 8.14, Step 4 shows an example of adding an extra attribute from the same XML.

        Let me know if you need further clarification!

        Cheers,

        Tim

         
    18. Nigel Hamilton

      March 25, 2014 at 10:51 pm

      Hi Tim,
      I am trying to apply the CoreDataHelper classes etc. to my existing app. The end goal is to get my existing app working on iCloud.
      I have hit a problem early on whereby my existing core data is lost. I am just trying to get the app to work as before, but with your classes, before going on to try iCloud. It looks like my existing data is stored at var/mobile/Applications/706etc.XXXX/Documents/myApp.sqlite, whereas the CoreDataHelper class is looking for it at var/mobile/Applications/706etc.XXXX/Documents/Stores/myApp.sqlite, I can where the “Stores” is added – in ApplicationStoresDirectory. I will have a look at changing this later, but I thought I’d ask you about this first, in case there is an important reason for having the Stores in the path.
      Thanks,
      Nigel

       
    19. Marc Bautista

      March 29, 2014 at 5:57 am

      Hi Tim,

      Can you kindly clarify this for me?

      + (void)saveContext:(NSManagedObjectContext*)context {
      if (debug==1) {
      NSLog(@”Running %@ ‘%@’”, self.class, NSStringFromSelector(_cmd));
      }
      [CoreDataHelper saveContextHierarchy:context];
      }

      I am confused as to the call +[CoreDataHelper saveContextHierarchy:context].

      CoreDataHelper does not have +[saveContextHierarchy:context:],
      It however does have -[saveContext].

      CoreDataImporter on the other hand have +[saveContextHierarchy:context:]

      I am assuming that the call that you are referring to CoreDataImporter as the receiver and not CoreDataHelper which is essentially [self saveContextHierarchy:context];

      Is this correct?

      Thank you very much

      Marc

       
      • Marc Bautista

        March 29, 2014 at 5:58 am

        BTW, this is in regards to the Errata.

         
    20. Marc Bautista

      March 29, 2014 at 6:27 am

      Sorry Tim,

      Wish I can edit my post but…

      Anyways, It was not CoreDataImporter I was referring to but the Deduplicator class.

       
    21. Jian Yan

      April 2, 2014 at 9:28 am

      Hello Tim,

      Thanks for the wonderful book!

      I do have one problem in the iCloud migration using your sample code. In some of my table I have column named “DELETED”, but when I migrate my local store to iCloud via deep copy, in some case the column get all “NULL” value afterwards. Is there anything I did wrong? All other data are copied fine. just that “DELETED” column get nullified.

      Thanks for advance!

       
      • Jian Yan

        April 8, 2014 at 10:38 am

        I found the reason. “deleted” is an undocumented reserve word for core data, which has conflict with method “isDeleted” if I access it by valueByKey. It cause random result.

        Thanks!

         
    22. Patrick Algrain

      April 2, 2014 at 8:54 pm

      Hello Tim,
      Great Book, thanks for it

      Newbie programming on Xcode, your book make me go forward very fast and I enjoy it.
      I have apply the whole book and the application work fine. But now, I would like to redo it adapting code and text in my language (French) just for exercise, but I have a problem on importing XML file,
      my language have a lot of accentuate characters (éàâî) and the importation block on the first of those found. Could you tell how I could solve this?
      Thanks for advance !

       
      • Patrick Algrain

        April 3, 2014 at 4:43 pm

        Solved, it was due to bad file format, when saved in UTF16 all accented characters are taken except the (&)
        Thanks

         
    23. sirsha

      April 3, 2014 at 11:07 am

      I’m getting tons of warnings in Objective-Zip. “Implicit conversion loses integer precision” for the most part. Is this a 64bit issue?

       
      • Tim Roadley

        April 3, 2014 at 11:29 am

        This is an issue introduced with later versions of Xcode that I only discovered this morning. I’m looking in to this.

         
    24. Michael F

      April 5, 2014 at 1:38 am

      Tim –

      In trying to perform the final migration in Ch 3 (Model 3 to 4) I never see any migration status in the migrationVC. The migration run – I see a slew of data in the logs but the screen never moves. I also never see the logging from

      -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

      so in one sense its not surprising I don’t see the updates. Any thoughts on where to look to address this?

       
      • Michael F

        April 5, 2014 at 1:53 am

        Figured it out – the key name I was using for the observer was misspelled. This would be a downside to KVO – no compiler awareness – but at least its working now.

         
        • Tim Roadley

          April 5, 2014 at 7:02 am

          Hi Michael,
          Glad you worked this out!
          Cheers,
          Tim

           
    25. Joyce

      April 8, 2014 at 3:30 am

      Hi Tim, thank you for the book, it really helps a lot.
      Here I have a question when I trying not to add empty Item when click Back button. I’ve tried many ways, such as delete the created item at ViewWillDisappear of the ItemVC, but it still adds to the PrepareTVC. Can you give me some advice? Thanks!

       
    26. eyestach

      April 17, 2014 at 2:37 am

      Tim!

      Things are looking very good, but loadStore runs before AlertView appears, shouldn’t it wait until the importing is finished?

      The CoreDataHelped gets instantiated at the end of ApplicationDidFinish….

      – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

      …..

      [[self cdh] iCloudAccountIsSignedIn];
      return YES;
      }

      CoreDataHelper::setupCoreData follows, I need to migrate a few new Rxs from my DefaultRecipes.sqlite into DB from earlier versions.

      – (void)setupCoreData { // like Late EasyiCloud //2/24/14

      if (!_store && !_iCloudStore) {

      if ([self iCloudEnabledByUser] && [self iCloudAccountIsSignedIn]) {
      NSLog(@”** Attempting to load the iCloud Store **”);
      if ([self loadiCloudStore]) {
      return;
      }
      }
      NSLog(@”** Attempting to load the Local, Non-iCloud Store **”);
      [self setDefaultDataStoreAsInitialStore];
      [self checkIfDefaultDataNeedsImporting];
      [self loadStore];
      } else {
      NSLog(@”SKIPPED setupCoreData, there’s an existing Store:\n ** _store(%@)\n ** _iCloudStore(%@)”, _store, _iCloudStore);
      }
      }

      The relevant part of my app’s – (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex follows:

      if (alertView == self.importAlertView) {
      if (buttonIndex == 1) { // The ‘Import’ button on the importAlertView
      // Deep Copy Import From Persistent Store
      [self loadSourceStore];
      [self deepCopyFromPersistentStore:[self sourceStoreURL]]; //_srcCTX -> impCTX
      } else {
      NSLog(@”Default Data Import Cancelled by User”);
      }
      // Set the data as imported regardless of the user’s decision
      [self setDefaultDataAsImportedForStore:_store];
      }

      As you know, the AlertView is kicked off in checkIfDefaultDataNeedsImporting method.

      Using your code in my app, the data from the existing (earlier DM version) appears in the RootView tableView before the AlertView appears asking for permission to Import Default Data.
      Ideally, if I am looking at this right,
      [self loadStore];
      should not run until the AlertView is dismissed.

      RootView should not appear until after the AlertView question was answered, Or ..?
      My understanding of GCD is minimal. My brother might say, it like I am trying to trim cuticles on a elephant to make it run faster.

      Everything about your writing and code is clear and just great.

      Mark

       
    27. bobburns22

      April 20, 2014 at 10:52 pm

      Hi Tim,

      Great Book! I love how it is written so you build on an existing application step by step. Great way to learn.

      I’m working through chapter 6 now, but there is something I’m trying to wrap my head around that maybe you can help with.

      My basic question is this: why is the core data stack accessed through the App Delegate? The AppDelegate is a shared instance so I can understand wanting only one instance of your core data model, but couldn’t the coreDataHelper class be a singleton as well? (If its not already with the use of the dispatch_once function). My theory is that the cdh property is accessed through the AppDelegate because that’s where everything gets initialized and since it’s already a singleton why not take advantage of that.

      Here is the line of code that is at the heart of the question:
      REBCoreDataHelper *cdh = [(REBAppDelegate *)[[UIApplication sharedApplication] delegate] cdh];

      Thanks!

       
      • Tim Roadley

        April 21, 2014 at 10:43 am

        Hi Bob,

        Thanks for buying the book!

        When you get to the final chapters of the book you will see a new class method called ‘sharedHelper’ makes its way in to CoreDataHelper, which eliminates the need to use the AppDelegate.

        Cheers,

        Tim

         
        • bobburns22

          April 21, 2014 at 10:47 am

          Cool. Thanks!

          Bob

           
    28. Ezequiel A

      May 2, 2014 at 3:56 am

      Hi Tim,

      I got your book two days ago and jumped directly to the iCloud implementation. I really like your explanation using Grocery Dude.

      I’m doing some tests to implement the Generic Core Data Classes in my app, but I still have some users running iOS 6.x. I tried to execute the example EasyiCloud on iOS 6.0 and I got a EXC_BAD-ACCESS error on the method listenForStoreChanges since NSPersistentStoreCoordinatorStoresWillChangeNotification is only available starting iOS 7.0.

      There is any way to workaround this?
      There are any other version compatibility issues with your code that I need to be aware of?

       
      • Tim Roadley

        May 2, 2014 at 8:51 am

        Hi Ezequiel,

        I haven’t tested adding pre-iOS7 support. Off the top of my head you could try adding something like this to the setupCoreData method of CoreDataHelper.m

        if (7.0 > [[[UIDevice currentDevice] systemVersion] floatValue]) {

        [self loadStore]; // the local, non-icloud store.
        return;
        }

        Give that a go and let me know what happens. You’ll probably want to do something similar to ensure that the ‘Enable iCloud’ setting is not visible in Settings > Grocery Dude too.

        Cheers,

        Tim

         
        • Ezequiel A

          May 3, 2014 at 4:07 am

          Hi ,

          I tried the fix with the same results. The issue here is with the core data notifications on listenForStoreChanges that is called from init regardless of iCloud or non-iCloud execution (is this statement correct?). However, with this approach my non iOS7 users will have no iCloud functionality.

          About the ‘Enable iCloud’ setting according to my research there is no way to hidden it programatically. An approach recommended on a website is to put the settings inside your app and present a settings/configuration icon on your main tabbar. This approach will make more evident for users the possibility of enable/disable iCloud functionality.

          An interesting reading about multiple version apps support is at http://www.raywenderlich.com/42591/supporting-multiple-ios-versions-and-devices (talks about iOS5 and iOS6).

          I think I will have to do the coding and update manually my app for core data support. But definitely, I will use your Generic Core Data Classes on my next app for iOS 7.0 and later.

          Thank you for your help and please let me know if you have any other suggestion or recommendation.

          Regards,
          Ezequiel

           
    29. Joseph

      May 14, 2014 at 4:03 am

      I really like you book “Learning Core Data For iOS”, it is helping me a lot. I came across your book while looking for books to help me in Core Data. I just got a position as an iOS Software engineer and I am trying to learn as much as possible as quickly as possible. So far this has been a lot of help. I just hope that one day I will be as good as you are at this. I will be looking forward in reading anything else you publish on iOS.

       
    30. Nigel Hamilton

      May 14, 2014 at 6:47 am

      Hi Tim. I’ve been trying to apply the Dropbox chapter to my own app. The code you have supplied is really great – thanks. I think I have it working on my iPhone. I was also hoping that I could create a backup on my phone and then restore on my iPad. Should that be possible? Thanks for a great book.

       
      • hamiltonappsNigel

        May 14, 2014 at 9:27 pm

        Actually, I have it working on the simulator. I then tried on iPhone/iPad and thought there was a problem moving from device to device. Actually, I now realize I can’t do a restore on the phone itself. Ok on simulator, doesn’t work on phone.
        I wonder if it is to do with the folder structure in the phone. I couldn’t use your code as publish. You start with your .sqlite file in Documents\Stores whereas I have mine starting in Documents (as that is where the existing app will have stored it on user’s devices.

         
        • hamiltonappsNigel

          May 14, 2014 at 9:38 pm

          To get it going in the simulator, I created the Stores_New (and Stores_old) at the same level as Documents i.e. not within Documents. I guess this is not allowed in the device.

           
    31. hamiltonappsNigel

      May 14, 2014 at 10:02 pm

      Probably my best approach would be to find out how to move my initial .sqlite file to a new Documents\Stores folder and then I can go back to using your code.

       
    32. mamyweb

      May 20, 2014 at 12:31 am

      hello, how can I edit CoreDataHelper and CoreDataImporter, to import data from a JSON, rather than a XML. Is there any example? Thank you!

       
    33. hayavadan

      May 23, 2014 at 4:00 pm

      I am going through your book it has been excellent so far. I am coming across a problem. I am unable to show Sections and section headers

      How program gets to know “these are sections”?

      [self.frc sections ] is the answer?????

      I do not know what i am doing wrong

      ( NSString *) tableView: (UITableView *)tableView titleForHeaderSection:(NSInteger)section {

      if (debug==1) {
      NSLog(@”Running %@ ‘%@’ “, self.class, NSStringFromSelector(_cmd));
      }

      /* DEBUG HELPER CODE FIND sectionForSectionIndexTitle*/
      NSLog(@”FIND OUT THE COUNT OF SECTIONS %@”, [[[self.frc sections ] objectAtIndex:section] name] );
      return[[[self.frc sections ] objectAtIndex:section] name];

       
    34. Brian Patterson

      June 2, 2014 at 5:12 am

      Hi Tim,
      I really like the book and is probably the best one out there for Core Data. I posted this code from page 110 CoreDataHelper *cdh=[self cdh];
      NSArray *homeLocations=[NSArray arrayWithObjects:@"Fruit",@"Pantry",@"Nursery",@"Bathroom",@"Fridge", nil];
      NSArray *shopLocations=[NSArray arrayWithObjects:@"Produce",@"Ailse1",@"Aisle2",@"Aisle3",@"Deli", nil];
      NSArray *unitNames=[NSArray arrayWithObjects:@"g",@"pkt",@"box",@"ml",@"kg", nil];
      NSArray *itemNames=[NSArray arrayWithObjects:@"Grapes",@"Biscuits",@"Nappies",@"Shampoo",@"Sausages", nil];
      int i= 0;
      for (NSString *itemName in itemNames)
      {
      LocationAtHome *locationAtHome=[NSEntityDescription insertNewObjectForEntityForName:@"LocationAtHome" inManagedObjectContext:cdh.context];
      LocationAtShop *locationAtShop=[NSEntityDescription insertNewObjectForEntityForName:@"LocationAtShop" inManagedObjectContext:cdh.context];
      Unit *unit=[NSEntityDescription insertNewObjectForEntityForName:@"Unit" inManagedObjectContext:cdh.context];
      Item *item=[NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:cdh.context];
      locationAtHome.storedIn=[homeLocations objectAtIndex:i];
      locationAtShop.aisle=[shopLocations objectAtIndex:i];
      unit.name=[unitNames objectAtIndex:i];
      item.name=[itemNames objectAtIndex:i];
      item.locationAtHome=locationAtHome;
      item.locationAtShop=locationAtShop;

      i++;
      }
      [cdh saveContext];
      The problem is that it is saying that “itemName is an unused variable”. I’ve looked at your code in the book and I don’t see what I have done wrong.
      Regards
      Brian

       
    35. Nick Hanson

      June 2, 2014 at 5:24 am

      Looks like there are possible a couple of errors in the book.

      You are told to create the “int i” variable, which is then used as item.name = [itemNames objectAtIndex:i].

      Surely as you are iterating through the itemNames array using fast enumeration, there is no need to create the variable i.

      You would simply do item.name = itemName

       
    36. Brian Patterson

      June 2, 2014 at 5:35 am

      Thanks for that Nick

       
    37. Brian Patterson

      June 6, 2014 at 6:02 am

      I don’t know if this is another error in the book but on page 142 when I add [self ensureItemHomeLocationIsNotNull];
      [self ensureItemShopLocationIsNotNull]; in both – (void)viewWillAppear:(BOOL)animated and – (void)viewDidDisappear:(BOOL)animated
      I get the following SIGBRT error. *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘executeFetchRequest:error: A fetch request must have an entity.’

       
    38. Crystal Twix

      June 13, 2014 at 6:30 am

      Is there a pro/con of making CoreDataHelper a singleton? I see different things on the web and stackoverflow including Apple’s documentation about not making your access to Core Data a singleton. Instead to pass the context to each view controller. Can you explain why a singleton was used for the CoreDataHelper? Great book btw!

       
    39. Brian Patterson

      June 25, 2014 at 7:57 am

      How did you create an xml file in numbers? How did you create an xml file? I am at a loss as to how this was done.

       
    40. Jun Jiao

      July 7, 2014 at 1:11 am

      Hi Tim,

      I really enjoyed reading your book Learning Core Data for iOS. It’s the most detailed and helpful material about core data I’ve read so far.

      I was playing with the EasyiCloud source code today and found a bug in the code which I’d like to discuss with you. It might be due to my limited understanding and not a genuine issue.

      In the following line in the unloadStore method in CoreDataHelper:

      ps = nil;

      You’re setting the local pointer to nil when psc successfully removes the store, which won’t affect the value of the underlying instance property. This will leave the actual store pointer with an empty psc and cause the removePersistentStore to fail the next time a merge happens.

      My suggested fix is to change the parameter of unloadStore to a pointer of pointer:

      – (BOOL)unloadStore:(__strong NSPersistentStore**)ps;

      so

      *ps = nil

      will set the actual store pointer to nil.

      Best regards,

      Jun

       
    41. Toy Collector (@toycollectorapp)

      July 18, 2014 at 10:35 am

      Thanks so much for this book. It has been really helpful in redesigning my app. One question that I can’t seem to figure out: How can I combine the Fetch Results Templates with the search feature. The Fetch Results are working perfectly (even with variables), but when I search, it search and returns data from the entire entity, and not just the data filtered from the template. I’m sure it’s something simple I’m over looking… Thanks!

      Zack

       
      • Toy Collector (@toycollectorapp)

        July 18, 2014 at 10:54 am

        Oh, wait! I think I answered my own question. For the search, I just drop the Fetch Results Template and build a compound predicate like so:
        NSMutableArray *predicateArray = [NSMutableArray array];
        [predicateArray addObject:[NSPredicate predicateWithFormat:@”sort1 BEGINSWITH[cd] %@”, _filter]];
        [predicateArray addObject:[NSPredicate predicateWithFormat:@”ANY nameKeywords.words BEGINSWITH[cd] %@”, searchString]];
        NSPredicate *compoundPredicate =
        [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];

        Seems to work well!

         
    42. James Qiu

      August 23, 2014 at 8:22 pm

      Great book Tim. I did enjoyed it.
      I am waiting for 2nd edition for iOS8, or a more advanced version which can combine with other frameworks. But be careful, don’t left readers into BaaS cloud without a back home ticket.- I am talking about PayPal shutdown StackMob in May 2014, which was used as Chapter 16 of this book.

       
      • Tim Roadley

        August 25, 2014 at 8:21 am

        Hi James,

        I won’t be writing an iOS 8 version because the publisher did not approve it :(

        Cheers

        Tim

         
        • bobburns22

          August 25, 2014 at 8:58 am

          Thats too bad Tim. Your book has given me many unknown insights into the workings of Core Data. Totally invaluable. An iOS 8 book I’m sure would provide more.

           
        • Tim Roadley

          August 26, 2014 at 11:16 am

          Oh wow, as it turns out the publisher never got my proposal. They’re reviewing it now… so maybe there will be an iOS 8 version!

           
    43. Dima Shmidt

      August 26, 2014 at 6:53 pm

      Hi Tim!
      Thanks for the book, it really helped a lot.
      I didn’t find any UIManagedDocument solutions in it. What do you think about it?

       
    44. Rick Michaud

      August 30, 2014 at 11:55 am

      Hi Tim,

      I just wanted to say that this book is awesome! I found far too many tutorials gloss over CoreData far too quickly. This book really helped remove the fog in my head about the CoreData framework…especially for an ancient Cobol, Pascal and C developer.

       
    45. eyestach

      September 3, 2014 at 5:22 am

      I just want to share this with anyone who is interested. It has been working for me for about a day now. Please, please let me know, if doing this is a bad idea. I can not think of one. I have bad results if I touch the ‘Merge” button in my app multiple times. Maybe it has been bad implementation on my part.

      I really like this site, Mark

      METHOD TO ENSURE THAT THE “MERGE” BUTTON FOR SEEDING IS USED AT MOST ONCE DURING APP LIFETIME

      0. Use NSString and not BOOL in KV_STORE. No need to add observer, except for learning

      1. In Constants.h :

      #define SEEDED_ICLOUD_MSG @”Have Seeded iCloud”
      #define ICLOUD_SEEDED_KEY @”iCloudSeeded”

      2. Before calling function to seed iCloud with non-iCloud data:

      NSUbiquitousKeyValueStore* kvStore = [NSUbiquitousKeyValueStore defaultStore];
      NSString* strMergeDataWithiCloudDone =
      [kvStore stringForKey:ICLOUD_SEEDED_KEY];
      NSComparisonResult *result = [strMergeDataWithiCloudDone compare:SEEDED_ICLOUD_MSG];
      if(result != NSOrderedSame)
      //put up UIAlert asking user if seeding is desired.

      3. If user chooses YES : set Value for Key after the merge is done.

      – (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
      if (alertView == self.seedAlertView) {
      if (buttonIndex == alertView.firstOtherButtonIndex) {
      [self seediCloudwithNoniCloudData];
      NSUbiquitousKeyValueStore* kvStoretore = [NSUbiquitousKeyValueStore defaultStore];
      [store setObject:SEEDED_ICLOUD_MSG forKey:ICLOUD_SEEDED_KEY];
      }
      }
      }

      4. Thereafter on all devices, for all time, the code

      NSUbiquitousKeyValueStore* kvStoretore = [NSUbiquitousKeyValueStore defaultStore];
      NSString* msg =
      [kvStore stringForKey:ICLOUD_SEEDED_KEY];

      should on any syncing device produce: msg == SEEDED_ICLOUD_MESSAGE

      5. For debugging use Preprocessor Macros definition CLEAN to reset iCloud

      if (_iCloudStore) {

      #ifdef CLEAN
      // CLEAN SLATE for iCloud
      DLog(@”[self destroyAlliCloudDataForThisApplication] now”);
      [self destroyAlliCloudDataForThisApplication];
      /// uses [NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:
      // options: error:
      NSUbiquitousKeyValueStore* kvStore = [NSUbiquitousKeyValueStore defaultStore];
      [kvStore setObject:@"" forKey:ICLOUD_SEEDED_KEY];
      [kvStore synchronize];
      abort();
      #endif

      }

       
    46. Nigel Hamilton

      September 5, 2014 at 5:59 am

      Hi Tim. I have applied your Dropbox code to my own app – thanks for such a good explanation. It works well apart from one slight problem. When I run on an iPad, and hit the button to go to the dropbox interface, the master left pane shows the dropbox backups (if any). However, if I have not yet linked to dropbox, the logon screen is displayed in a popover, until I successfully sign in. I am then left with a blank backups table, with Unlinked heading. If I return to a previous screen and then hit the dropbox button again, it correctly shows the backups. Somehow, I need to be able to detect when linking has occurred and reload the table. Any ideas on how to do this? Thanks.

       
    47. Podster

      September 10, 2014 at 3:39 pm

      Will you be able to at least post updates for your classes to work with iOS 8? I am currently have issues with current classes with Xcode GM release.

       
      • Tim Roadley

        September 15, 2014 at 8:39 am

        I’m focusing on updating the whole book to Swift at the moment, which is really time consuming. Happy to try and solve error messages etc in the mean time if you have them.

         
        • Podster

          September 15, 2014 at 3:54 pm

          Looking forward to the Swift version :) Find below some of the classes that are having issues.

          ——————-
          CoreDataTV.h
          /CoreDataTVC.h:21:31: ‘UISearchDisplayController’ is deprecated: first deprecated in iOS 8.0 – UISearchDisplayController has been replaced with UISearchController

          @property (strong, nonatomic) UISearchDisplayController *searchDC;

          But if you change the UISearchDisplayController to UISearchController you get lots of error in different places and classes.

          ——————–
          CoreDataTV.m
          /CoreDataTVC.m:97:12: Enumeration values ‘NSFetchedResultsChangeMove’ and ‘NSFetchedResultsChangeUpdate’ not handled in switch

          – (void)controller:(NSFetchedResultsController *)controller
          didChangeSection:(id )sectionInfo
          atIndex:(NSUInteger)sectionIndex
          forChangeType:(NSFetchedResultsChangeType)type {

          Thanks.

           
    48. Nigel Hamilton

      September 13, 2014 at 11:44 pm

      Hi Tim. I added drop box support to my app. I created the Dropbox API app as you described. For this to be used by the public, do I need to change anything in the Dropbox API app settings e.g. Get Status changed to Production?

       
    49. Fayyaz Syed

      September 14, 2014 at 8:05 am

      Hi Tim, and thanks very much for writing this book. I’ve bought it, and am now going through it chapter by chapter. I completed chapter 5, and this is where I am having some trouble. When I try to clear items from my GroceryDude Shop tableview, I get the following error:

      2014-09-13 18:02:59.883 GroceryMan[1777:60b] CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0] with userInfo (null)
      2014-09-13 18:02:59.889 GroceryMan[1777:60b] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]‘
      *** First throw call stack:
      (

      I’ve run your code, and it works fine, and I’ve tried to go through the chapter carefully to make sure the code was entered correctly, but can’t seem to figure out the issue. Can you help my identify the problem here?

      Thanks very much for your time, and thanks very much for writing your book.

      Take care.
      Sincerely;
      Fayyaz

       
      • Fayyaz Syed

        September 14, 2014 at 10:18 am

        Hi Tim, I’m really sorry, but please ignore my post. The problem unfortunately is that I’m an idiot. I’ve fixed the problem in my code. Thanks so much for your patience.

        Sincerely;
        Fayyaz

         

    Leave a Reply