Two NSArrayControllers and a relationship (CoreData) - cocoa

Is it okay to do it like i did … ?
Created nsarraycontroller in entity mode controlling 'Accounts'
Created nsarraycontroller in entity mode controlling 'Transactions' and bound to the 'Accounts' nsarraycontroller with key 'selection' and model key path 'transactions' (to-many relationship from accounts to transactions)
I'm askin cause i think something is kinda messed up. Because when i create a button, and try to connect it with the add:(id)sender of the transactionsArrayController, it doesn't seem to add it ... Where can be the problem ? addObject works as expected. But I want to use add:(id)sender and also be sure the code is working as it has to ...

Yes, it's quite normal to base the contents of one array controller on some property of another (including selection.someCollection).
Do you receive any errors in the console when you add? (Hint: include them in your question) Are both array controllers' Managed Object Contexts bound to a valid MOC? What are all your other settings for both array controllers set to? (Another hint: you need to be a lot more specific about describing your setup.)

Related

Two NSArrayControllers on one NSManagedObjectContext?

I have two NSArrayControllers in my MainWindow.xib and want to use both of them with CoreData. Both are using entities of the same type from the same data model. These two array controllers are bound each to their own table views (one for generated data, one for stored data).
The first array controller is connected to the managed object context in AppDelegate but what do I do about the second array controller? It doesn't seem it can be connected to the same managed object context. If I compile now I get the error Cannot perform operation without a managed object context for the second array controller.
To answer this question on my own now:
The binding inspector in IB has bindings on NSArrayController for the Managed Object Context. I wasn't completely sure that this is the right way to bind the array controllers but it obviously seems to be so.

Core Data: "-add<RelationshipKey>Object:" not called

Let's presume I have an entity BikeRider with a relationship property called helmets.
I have an array controller bound to the app's managed object context, with entity set to BikeRider. There's a tableview that lists all bike riders.
Then, I have a second array controller, bound to the app's managed object context, with entity set to Helmet. Additionally, it's bound to bikeRiderArrayController.selection. There's a second tableview that lists all helmets for the selected bike rider.
I also have two buttons for adding and removing helmets. The setup works apparently flawlessly.
Except, of course for one small thing: it looks like -addHelmetsObject:, -removeHelmetsObject:, -addHelmets: and -removeHelmets: never get called. This means some code for setting up observation of each helmet's color property never gets called.
What am I missing? Isn't overriding addHelmets: et al (with proper willChangeValueForKey: et al notifications) the right way to get notified of additions?
Do I really have to [self observeValueForKey:#"helmets". . .] and then [oldValue minusSet:newValue] and vice versa to figure out which objects were added or removed? I could swear the methods were being correctly called in the past. Maybe some key element of the setup is now different.
This has never worked properly through NSArrayController. From Apple's docs:
Custom relationship set mutator methods are not invoked by an arraycontroller
Problem: You have implemented set mutator methods for a relationship as described in “Custom To-Many Relationship Accessor
Methods,” and have bound the contentSet binding of an
NSArrayController instance to a relationship, but the set mutator
methods are not invoked when you add objects to and remove objects
from the array controller.
Cause: This is a bug.
Remedy: You can work around this by adding self to the contentSet binding's key path. For example, instead of binding to [Department
Object Controller].selection.employees, you would bind to [Department
Object Controller].selection.self.employees.

Cannot remove an observer ... for the key path "..." from ... because it is not registered as an observer

I have a Core Data model with two entities: A and B.
A has a relation to one or more Bs.
B has a property bValue.
I create many instances of a class and some of them invoke a notification. This notification called a method that creates a new B entity and adds it to A. The instances are created using NSThread in order to make the UI more responsive.
This works only fine then there are not too many notifications invoked. Or at least not too many at 'the same time'.
Then I get this exception:
Cannot remove an observer <NSArrayController 0x10016c150> for the key path "bValue" from <bValue 0x104e55c30> because it is not registered as an observer.
Yes, B is bound to an NSArrayController.
If I remove this ArrayController from the NIB file, everything works
fine (except everything the ArrayController has to do)
If I create many Bs and add them to A elsewhere (outside the notification method)
everything works find, also with the ArrayController.
Can someone help me please?
(Please excuse my poor pronunciation.)
You said you're doing this work on a separate thread. If so, you need to make sure you are using a separate NSManagedObjectContext. You cannot use the same NSManagedObjectContext on multiple threads, nor can you use a NSManagedObject associated with one MOC in another MOC. Each thread needs to interact with CoreData independently.

Attaching an object to another context in EF 4

I have a baseclass in my website with a property: CurrentUser.
The get method of this property will create a new context and get a User object from the database based on auth cookie information. So far so good.
But since the context is closed, all I can do outside this, is to call properties directly under User, for example FirstName.
But as soon as I try to get a relation for example, like CurrentUser.UserOffices this won't work since I didn't include UserOffices in the query.
Is there a way to create a new context outside the baseclass which I can attach the CurrentUser object to? I have tried ctx.Attach(CurrentUser) with no luck.
You may wonder why I don't include UserOffices. This is simply because there are very many relations to different tables and I don't want to include them all since it differs between my web pages what relations are needed.
Any ideas?
You can try to Attach your entity and then explicitly load property:
ctx.Attach(CurrentUser);
ctx.LoadProperty(CurrentUser, u => u.UserOffices);
I'm not sure if this works with POCOs.
You can also query for object again with Includes specifing navigation properties you need.
The other choice is simply load UserOffices with Linq-to-entities query restricting where condition to current user.

Cocoa bindings: custom setter methods?

I'm using Cocoa bindings to manage a table of objects. I understand how bindings work but I've run into a slight problem. Managing the table of objects would be fine and dandy, except that those objects have to manage actual bluetooth hardware. I'm working off of a framework that provides a class representing a connection to this hardware, and have made another "manager" class the makes it key-value compliant. In other words, this manager class has to be able to connect and modify its "connect" status in its properties dictionary, be the delegate of this hardware and modify properties, and update the hardware with changes made.
However, whenever I set new values within the object itself, like in a "connect" method that would change the "connect" key's value to 2 (looking), (i.e. propertiesDict = newDict), the change is not seeming to be picked up by observers that it is bound to. I've looked at the observeValueForKeyPath:ofObject:change:context: in the NSKeyValueObservingProtocol. However, I don't know what to do with the context argument.
I hope that makes sense... but if anyone has any ideas I'd love to hear them.
Your question isn't totally clear, but if I'm understanding it correctly the issue might be because you need to send manual KVO notifications before and after you change a value in the embedded object. For instance, [self willChangeValueForKey:#"connected"]; and [self didChangeValueForKey:#"connected"];.
There are three ways to update a property/attribute in a KVO compatible way:
Using the property setter (specified in #property declaration or generated by #synthesize)
Calling -willChangeValueForKey: and -didChangeValueForKey: before and after you change the property value in any way.
Calling -setValueForKey:

Resources