0

Background:   I built an app w/ inexperience. It uses bindings, a NSArrayController subclass and Core Data/iCloud. The experience level caused a lot of code unnecessary writing, yet the app worked ok. A button linked to the NSArrayController add: method triggered newObject and addObject:. Removing never worked and led me to look at contentArray binding . A week ago, I began cleaning the app to more thoroughly use the simplicity of bindings. (Unfortunately, complexity also entered into this problem.)

Assumptions:   1) add: and remove: methods would automagically fire the methods to create and delete objects. Many simple tutorials seem to work this way. 2) The add:, addObject:, remove: and removeObject: methods do not need to be overridden.

Problem:   addObject: and removeObject: do not get called (after some point of change) unless they are explicitly called in the add: or remove: method. I have never had the functionality of deleting both the array controller and managed object with a simple click on a remove button.

Question:   What is required for the Core Data managed objects to be added and removed?

Other info:   The array controller pictured below has Custom Class set to CheckinArrayController. The Core Data stack is initialized in AppDelegate. The newObject method has been overridden to preset some attributes.

EDIT: Override in array controller subclass add:, newObject, addObject:, and arrangeObjects:

Code in Array Controller (NSArrayController subclass)

@implementation CheckinArrayController

- (id)newObject {
    id newObject = [super newObject];
    //  do object set up here ....
    return newObject;
}

- (void)add:(id)sender {
    /*  without the next 2 no object is added, although this is called
        NSManagedObject *newItem = [self newObject];
       [self addObject:newItem];    */
}

- (void)addObject:(id)object {
    [super addObject:object];
}

- (void)remove:(id)sender {
    [super remove:sender];
}

- (void)removeObject:(id)object {
    [super removeObject:object];
}

@end

Current array controller connections:

enter image description here

David
  • 3,285
  • 1
  • 37
  • 54
  • Did you put the array controller in Entity Mode? – Willeke Aug 23 '16 at 20:30
  • Yes. With the entity name 'Checkin' (from data model) and Prepares Content checked. – David Aug 23 '16 at 20:38
  • Btw if you bind `Selection Indexes` of the table view to the array controller, you can bind `enabled` of the buttton to `canRemove` of the array controller. Same for the add button and `canAdd`. – Willeke Aug 23 '16 at 20:39
  • Which methods did you override? – Willeke Aug 23 '16 at 20:41
  • @Willeke See edit to OP. – David Aug 23 '16 at 20:44
  • Show us your code. – Willeke Aug 23 '16 at 20:50
  • @Willeke Before adding code, can you confirm my assumptions are true? I am concerned that code will hide this issue. – David Aug 23 '16 at 21:18
  • Your assumptions are true. That's why I'm interested in your overrides. Do the buttons work without the overrides? – Willeke Aug 23 '16 at 21:40
  • @Willeke No. If I comment/remove the methods `add:` and `addObject`, nothing happens. See edit. – David Aug 23 '16 at 21:46
  • Is there a chance that the delegate object in your xib is not the actual application delegate? If you bind the MOC through the application with a keypath of `delegate.managedObjectContext` does the behavior of the app improve? – stevesliva Aug 24 '16 at 00:35
  • @stevesliva No. It doesn't matter when I bind Delegate.managedObjectContext, Delegate.self.managedObjectContext or Application.delegate.managedObjectContext. They all display objects and only call `add:` or `remove:` – David Aug 24 '16 at 02:11
  • `add:` doesn't do anything. Maybe I don't understand the problem. What do you mean by "`addObject:` and `removeObject:` do not get called (after some point of change)"? – Willeke Aug 24 '16 at 06:31
  • @Willeke Thanks for persistence. Prior to a point of redesigning the application, `addObject:` and `removeObject:` were called automatically after `add:` and `remove:`. This backs up my assumption 1. After the redesign, the array controller subclass no longer adds or removes an object without the add/removeObject methods being explicitly called. `add:` is an action connection and is called. Something is missing that causes the array controller to actually add or remove those objects. I wonder if its the contentArray binding, because this binding allows for 'deletes objects on remove'. – David Aug 24 '16 at 12:37
  • @David - just making sure. If you have ever removed / modified / recreated that delegate object, you can end up with two MOCs... the one your old code talks to, separate from the one you are binding to. Just a worthwhile point of debug. – stevesliva Aug 24 '16 at 13:55
  • @stevesliva Good point. Looking into this. – David Aug 24 '16 at 13:57

1 Answers1

0

I would suggest creating a convenience init in your ManagedObject class. Here is another SO question that outlines this:

Designated Init for Managed Object

Call this init method when you want to create a new Managed Object. Your arraycontroller has a managedObjectContext from the bindings you have set up.

I use it like this:

let entity = NSEntityDescription.entity(forEntityName: "yourEntityName", in: managedObjectContext!)
let object = YourManagedObjectClassName(property1: "property1 entity: entity!, insertIntoManagedObjectContext: managedObjectContext)

I use the stock removeObject methods in the NSArrayController base class to delete objects.

removeObject Documentation

Chris
  • 335
  • 3
  • 10