Core Data and bindings - binding checkbox to result of many-to-many relationship - objective-c

Core Data model
I have a many-to-many relationship between two of the principal entities; call them Item and Tag. There will be a large number of Documents. Each may have 0 to an arbitrary number of tags.
Each Item entity relevantly has an attribute called name, and a to-many relationship to Tag called tags. Each Tag entity relevantly has an attribute called name, and a to-many relationship to Item called items.
To display them, within the same window, I have: (i) an NSTableView (itemTableView), fed by an NSArrayController (itemArrayController), showing all Items; and (ii) an NSTableView (tagTableView), fed by a different NSArrayController (tagArrayController) showing all Lists.
tagTableView
In the tagTableView, the Table View is bound to tagArrayController, with controllerKey arrangedObjects.
There is only a single table column. The textfield in it is bound to Table Cell View, to model key path objectValue.name. That works so far; it displays all of the lists as expected, and sorts properly when I add a sort descriptor.
Everything has been set up using interface builder in Xcode.
The problem
I have added a checkbox into the tagTableView, in the same table column as the textfield. I am trying to implement two things:
The checkbox should be checked if the user has previously associated the Item with the relevant Tag. If not, the checkbox should be unchecked.
If the user checks an unchecked checkbox, I want to establish a relationship between the two; if the user unchecked a checked checkbox, I want to break that relationship.
The underlying behavior pattern is that the user will not necessarily have control over the tags and may not be able to create them. They are to choose from existing tags, and therefore should be able to see which ones exist, and be able to check/uncheck those that apply.
However, I can't see how to implement this.
Part solutions so far
I can see a possible way to do at least the first task programmatically, roughly along these lines:
Monitor tableViewSelectionDidChange for itemTableView
For a change, update the data source for tagTableView manually, and work out checkbox state by checking them for those Tags which relate to the Item entity that has just been selected, and otherwise unchecking them
However, this looks likely to add complexity, and ideally I would like to do this with bindings if possible.
I have reviewed the Apple Core Data and Bindings references, all the Cocoa books I have, stack overflow and I've also done extensive googling. I have found lots of similar questions (e.g. http://lists.apple.com/archives/cocoa-dev/2011/Mar/msg00164.html) but no answers.
I've also found a way that might work programmatically, but which seems to be like my idea above, at the expense of being able to use bindings (e.g. http://www.raywenderlich.com/14742/core-data-on-ios-5-tutorial-how-to-work-with-relations-and-predicates)
The only relevant question on this site -- Core-Data Check Box Cell with many-to-many data -- is not answered to a level that I can make use of.
It would seem to me that this should be a prime candidate for bindings. I should be able to ask the itemArrayController what Tags (if any) have a relation to its selected item, and then set the checkbox to ticked if it matches the relevant Tag, and unset it if it doesn't. I would expect I should be able to do this within the bindings for the checkbox itself, in interface builder. But I can't work out what model key path or binding to use, or what to set the cocoa bindings for the checkbox to. Am I missing something obvious? Thanks

Related

One Core Data Entity Per NSPersistentDocument?

What's the best way to use Core Data if each document on disk corresponds to one Entity instance?
I have a data model file with one entity, and that entity has one attribute of name text and of type Text.
I have a Document.xib that has an NSObjectController that is set to 'Entity' mode and gets the managedObjectContext from the File's Owner. I have an NSTextField that is bound to the Object Controller for the Controller Key 'selection' and the Key Path 'text.' (This is just a test so I can figure out how Core Data works, but my eventual app will also only have one Entity instance per Document)
When I create a new document the textfield says 'No Selection' and is disabled.
I imagine that if I had a Table View or some other kind of way to select from among entity instances the selection would work but I don't nor do I want to. How can I hook up the NSObjectController to only have one Entity instance and to automatically 'select' it?
The intended behaviour is that I type something into the NSTextField, hit Save, close the document, re-open the document and the string in the textfield persists.
This is probably a really basic question but I can't find any tutorials or documents that would address this seemingly simple use case.
Ok, well I haven't figured it all out but my particular issue was being caused by the fact that nothing was being created. I switched out the NSObjectController for an NSArrayController, created an outlet for it in Document.m and added this to windowControllerDidLoadNib:
if (![self.arrayController selectedObjects]) {
[self.arrayController add:#""];
};
Now it seems to just manage the one Entity object.

Add Control after Items in GridView Group

I'm currently developing a Windows 8 Store app that uses a Grouped GridView in the HubPage showing Highlights for some Categories. So far, when clicking the Header you see More Highlights for this Category.
Now i want to add a control at the end of every Group leading the User to the "non-highlight" Category site, where just all the Items of this category are displayed.
Is there an easy and elegant way to do this - propably with a Template is suppose.
( i think the latest Bing-News-App has a similar feature )
Thanks in advance for every help.
There are a couple of ways you can do this.
You can add an arbitrary object to the end of your group, then use a DataTemplateSelector to style it.
You can create your own VariableSizedWrapGrid with the control added to the end in the constructor (slash "Arrange"). You can then add an arbitrary click handler as a dependency property and only show the button if the click handler is set, so you can reuse this on other pages, etc.
You can change the GroupStyle to include something similar at the end of the group, but it likely won't animate with the other items in the group (if that's important to you).
The easiest one to do is probably the first one. If your group is a list of SampleItems then make a subclass of the SampleItem class called something similar to TerminalSampleItem. Create a template for it (like you've made other data templates). Make an ItemTemplateSelector that has two properties, NonTerminalDataTemplate and TerminalDataTemplate (assuming you only have two data templates). Have the SelectTemplateOverride function check for (item is TerminalSampleItem);

GridView Control with different child categories that have no relationship to each other

I may be missing something here so I apologise if this question may come across as obvious.
In a XAML WinRT app, I can have a GridView control that I can throw a collection of stuff at, and then using DataTemplates etc I can render that stuff on screen.
How can I take this a step further and have a single “master” GridView control which contains several sections which get their data from different places and exist within the app as different collections of stuff?
For example, take the built in Games app. Here we have different sections – Spotlight, Friends, Game Activity etc which are all very different from each other, have different data and are displayed in different ways but they all exist within the same GridView control.
How can this be done?
I do hope this makes sense
Kris
If I understand your requirement correctly, you want to have a group of groups, and display each of the child groups using different templates.
The way I did it was to derive all the child items from a common base class (or you could build a group of groups of Objects, I suppose). Then we used the DataTemplateSelector to pick the appropriate template for each item in the master GridView.
We had to go a step or two further than that in practice, but that's the theory behind how I achieved a similar goal.

Additional actions when NSManagedObject is deleted

I have a core data 'ShoppingList' which contains 'Item' objects. I store a display order as an attribute of each item.
I would like to update the display order of all other items in the shopping list whenever an item is deleted. The code to do this is working fine when I use it in my view controller (from where the item is deleted), but since it is really related to the business objects and not the view, it would be better placed in either ShoppingList or Item.
Ideally, I would like it incorporated into the deletion of the item. So far I have tried the following:
1) Customize the standard Core Data generated ShoppingList.RemoveItemsObject (making sure to observe KVO before.after). What's strange about this way is that the item passed is stripped of its relationships to other core data entities before it gets to my code, which I need to process display orders correctly.
2) Customize Item.didTurnIntoFault. Same applies - but even attributes of the item are gone by this stage.
One answer would be to simply define a new method on ShoppingList that does my processing and then calls the original removeItemsObject. But I would prefer to know that whenever an item is removed, from anywhere, this is taken care of. This works nicely when I customize awakeFromInsert, for example - I know that whenever an item is created certain things are setup for me. But I'm surprised there's no equivalent for deletion.
Did you try to implement prepareForDeletion? Sounds like it's exactly what you're looking for.
The doc says:
You can implement this method to perform any operations required before the object is deleted, such as custom propagation before relationships are torn down, or reconfiguration of objects using key-value observing.

Core data, NSArrayContainer Arraycontent of many arrays

I've got three entities in my application so far: tag, feed and story
A tag has got a to-many relationship to feeds and feeds has got a to-many relationship to story.
I've got an NSArrayController for each entity, one named tags, one named feeds and one named stories.
They all share the same 'managedObjectContext' which they get from the file's owner. the content set of the AC named feeds is bound to 'tags' controler key: selection, key path: feeds
I want the content set of the third array to be bound to all of the stories in all of the feeds in the selected tag: i tried to use the key path: "#unionOfArrays.stories" but couldn't get it to work.
Any idea how i would go about this?
First of all, there's one thing in your question that's inconsistent with getting something working:
They all share the same
'managedObjectContext' which they get
from the file's owner
When I set this up in IB, it just didn't work. You surely mean you bound the managedObjectContext to that of the App Delegate.
Assuming you want to see all the stories in the selected tag, here's a few mistakes you might have made in your setup.
1. Check Inverse Relationships
For all the relationships you mention, you need to set the inverse for each relationship.
For the one to many tags->feeds relationship, you'd have a to many relationship in the tags elements called "feeds", which you've described.
You'd also have a to one relationship in the feeds entity called "tag".
You'd select the inverse relationship as being feeds as shown below:
Single Feed Relationship http://img20.imageshack.us/img20/2557/tagsinglefeedrelationsh.jpg
2. Link Up Stories
You don't mention how you've created any of your Stories. Assuming you're not doing anything in code, I'd have 4 Array Controllers:
Tags
Feeds in Selected Tag
Stories in Selected Feed
All Stories in Selected Tag
If you just have a Stories Array Controller whose Content Set isn't bound to anything, you'll be creating stories effectively in a vacuum - they won't be linked to any feeds or tags, which might be why you're getting these errors.
3. Setup "Stories in Selected Tag" Controller
You need to set the Content Array, not the Content Set.
Bind the Content Array to the "Feeds in Selected Tag" Controller.
Key: arrangedObjects
Key Path: #unionOfArrays.stories
This sends the Key Path stories to every object in the "Feeds in Selected Tag" Controller, thus getting all the Stories in all the Feeds in the selected Tag.
4. Rock and Roll!
We're done. If you're really struggling getting this set up, let me know and I can post the link to the XIB file I've made.
You can try #distinctUnionOfSets.stories. All Core Data 1-n relationships are implemented as sets.