2

I'm new to SWIFT programming and am trying to do a simple app to learn to use core data and bind it to display in an app. I've looked at loads of examples but all seem to be old. I am working in XCode 9.

I started with a MacOS Cocoa app with Core Data. I have a simple entity called "Workout" with 4 attributes date, seconds, sport and rpe.

I then added a Array Controller under the view controller scene. I added a Table view which set the Array Controller as the data source. I've added buttons to add and delete linking to array controllers add and remove methods.

I think all I need to do now is to bind the Array Controller to the managedObjectContext of my Core Data Model. This is found in the AppDelegate. However when I select the Array Controller and go to Bindings and select Parameters the only options to bind to are "View Controller" and "Shared User Defaults Controller". I've selected View Controller but cannot figure out the Model Key Path to link in to my data model.

I feel I must be missing something obvious. I feel there must either be a way to bind to the AppDelegate or a Model Key Path from the View Controller but I can't figure out either. Any help much appreciated.

Steven Lord
  • 253
  • 4
  • 15

2 Answers2

3

In a storyboard based project there is no (binding) reference from a view controller to the AppDelegate class.

A solution is to add a property and override init?(coder in the view controller

@objc let managedObjectContext: NSManagedObjectContext

required init?(coder: NSCoder) {
    self.managedObjectContext = (NSApp.delegate as! AppDelegate).persistentContainer.viewContext
    super.init(coder: coder)
}

then bind the ManagedObjectContext to ViewController -> managedObjectContext.

In the Attribute Inspector of the array controller don't forget to set the Mode to Entity Name, insert the entity name and check Prepares Content.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thanks for such a quick response. I put the following code in view controller as my AppDelegate doesn't have a managedObjectContext parameter: required init?(coder: NSCoder) { self.managedObjectContext = (NSApp.delegate as! AppDelegate).persistentContainer.newBackgroundContext() super.init(coder: coder) } . still getting an error though: [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key managedObjectContext. – Steven Lord Sep 21 '17 at 15:57
  • I updated the answer to consider the `NSPersistentContainer` syntax and fix the KVC issue – vadian Sep 21 '17 at 16:02
  • thanks. Thats helped me as I was using .newBackgroundContext() rather than .viewContext – Steven Lord Sep 21 '17 at 16:40
  • This saved me after days of searching what was wrong with my project – Mark Feb 24 '18 at 04:16
  • I'm trying to follow these instructions to fix the same problem in Swift 4.1, but I'm still running into the key value coding-compliance exception. Has Apple changed another thing? Should I add a new Question for the newer version of Swift? – mpounsett Apr 17 '18 at 16:13
  • @mpounsett I'm using this syntax in a lot of Swift 4.1 projects. Make sure that all bound properties are marked with `@objc` – vadian Apr 17 '18 at 16:25
  • I've only made two changes to the array controller: set the Object Controller mode to Entity Name and set the entity name to `Person` (my only Entity so far), and bound the Managed Object Context to the view controller with the Model Key Path of `self.managedContext`. That in turn is defined in the View Controller class as `@objc dynamic let managedContext : NSManagedObjectContext = ((NSApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext)` – mpounsett Apr 17 '18 at 16:44
  • @mpounsett The attribute `@dynamic` is pointless for a constant and I recommend to initialize the context in the `init(coder` method as described above. – vadian Apr 17 '18 at 16:50
  • aha! Found an unrelated problem after more searching. For some reason the View Controller in my storyboard wasn't set to the correct class name from my swift code. Very embarrassing. :( – mpounsett Apr 17 '18 at 17:14
0

To fix [<Core_Data_Binding.ViewController 0x6080000c4600> valueForUndefinedKey:]: this class is not key value coding-compliant for the key managedObjectContext change let managedObjectContext: NSManagedObjectContext in vadian's code to @objc let managedObjectContext: NSManagedObjectContext. XCode 9 by default does not expose properties and methods to Objective C: The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

Jędrzej
  • 11
  • 3