Reputation: 12005
Let's say I have a NSTableView which is currently using an NSArrayController that is pulling its data from Core Data. What is the best way to popular the table view from two different data sources, one being the local core data and the second being a remote webservice call.
What I want to achieve is spotlight style results table which as the user types will show instant local matches from core data and remote matches as they come in from remote web-service calls.
I'm new to Cocoa and come from a iOS background so NSArrayControllers are new to me.
Is subclassing NSArrayController possible and could I somehow achieve this or is there a more traditional approach using just the NSTableView.datasource protocol and glueing it all together in a View Controller.
Upvotes: 1
Views: 297
Reputation: 61228
An NSArrayController
is simply a convenience controller that observes some array for changes and updates the UI (or vice-versa). What you're really asking is "how do I create a combined array of matches retrieved from a Core Data store as well as external sources?". When you put it like that, the solution becomes a bit more obvious.
While convenient for simple cases, an NSArrayController
that's directly wired to a fetch request is rather dumb once you step outside "simple". Let's ignore the array controller for now, since this is actually two separate issues (managing a collection built from two disparate sources, and using an array controller with an array or set you manage yourself vs. a table data source).
Let's say you have a property on some controller called results
as an NSMutableArray
. To build your results, you'll combine those of two operations: 1) creating and executing an NSFetchRequest
yourself, and 2) creating and executing some network operation. I'm not going to go into detail on either of those two operations because there're plenty of valuable sources of information regarding those approaches, but it really is as simple as combining the two sets of results as they become available into your results
array.
As to the array controller (if that's the way you want to go), all it does is provide a simple means to use Cocoa Bindings to bind your UI to your model (results
array) via a controller (itself). That's it. It has two modes: managing a collection of the specified class (NSMutableArray
in this case) and a collection of instances of an entity from a Managed Object Model, via a fetch request executed against a Managed Object Context (ie, "Core Data mode"). Since you mean to manage the collection yourself, "Core Data mode" won't work for you. You want to configure it to manage a mutable array and not use an entity / MOC / fetch request at all (since you'll be managing that bit yourself). The trick there is to avoid "changing the array behind the array controller's back" and make sure you add and remove objects to/from the array via the array controller's methods so it knows the array's contents have been changed and can update / sort / etc. accordingly.
But, as you suspected, you can also skip the array controller entirely and just use the NSTableViewDataSource
protocol. Not only is there nothing wrong with this approach, it's actually superior in many ways when dealing with a custom case like yours. Sure, you'll have to manage selection changes (via the NSTableViewDelegate
protocol) as well as maintaining sort, but these are rather trivial things to do when you consider the level of control you gain over your collection. You could even easily manage "group header" markers in your collection and use the appropriate delegate methods to separate "Local" from "Remote" in your table using nice floating header rows.
I hope this helps.
Upvotes: 3