How can I bind an NSTableView with 2D data at the backend? - objective-c

I am new to mac, and I am in trouble. I need to bind NSTableView to 2D data at the back end so that I can have dynamic update of data at the front end. I have 5*10 data at the back end that I want to bind it to NSTableView. I have tried almost every approach, read every article, implemented examples from the internet but it isn't working.
I have tried different ways to store my 2D data and to connect it with the NSArrayController, but no results. I tried to represent a row with NSMutableDictionary with 5 different keys representing the 5 columns and their values respectively and then encapsulated the the dictionary object in an NSMutableArray object. Tried to bind NSTableColumn with the NSArrayController as well.
I would be obliged if anyone can tell me what data structure should I use, how many NSArrayControllers or NSObjectController should be there and what should be the correct values of controller keys and model in path in the inspector for every element involved. I would appreciate if anyone can provide me with an example closely related to the problem above.
Regards
Umair

You can't use Bindings for this. Bindings in a table view is for displaying a one-dimensional list of objects, where the columns are properties of each object.
In your case, every row-column intersection is a discrete object. Therefore, you need to implement a data source, if not use or create a different view entirely.

Related

Issue in lazy loading the table view

I am badly struck in a issue where I am trying to populate the nestableview lazily. Below is my approach.
I have created a custom class PRIList where it has an instance of array to manage the models.
I have bound the priList.items to the array controller in the xib where items is not an instance in PRIList but to support lazy loading I have implemented the methods countOfItems and objectInItemsAtIndex:.
Initialy when I populate the PRIList I populate few objects (say 50) with valid objects and rest with the faulty objects. In the objectInItemsAtIndex I check if the item at particular index is valid or faulty. If it is faulty I fetch next set of 50 objects.
What I understand is NSArrayController calls the method objectInItemsAtIndex for only the visible rows in the table view. But the problem here is as soon as set the PRIList the objectInItemsAtIndex method is called for all the objects. This is even called when some selection is changed in table view (the stack trace shows this method is called from [_NSModelObservingTracker startObservingModelObjectAtReferenceIndex])
Basically I want to fetch the records whenever the user scrolls down in the table view.
I followed the same approach in a different project in Lion. It worked there. Currently I am in Mavericks.
I tried overriding the isCompatibleWithResponsiveScrolling in the custom table view and returned it to NO. Still no luck.
Any help is very much appreciated.
First, have you assigned or bound the sort descriptors of the array controller? Or set any columns to automatically generate sort descriptors? (I'm not sure that latter is relevant. It depends on whether the column is sorted by default.)
In any case, if the array controller feels the need to sort the objects in order to arrange the objects, then it will need to load all of the contents. I was under the impression that it always does so, anyway, although you report that it works.
For an issue like this, I'd recommend that you go for full manual control. That means not using bindings or an array controller. Use a data source.

Modifying the results of a Core Data fetch request before displaying them

I've got an application which pulls back data from a database using Core Data, and displaying it in a custom cell in a UITableView, via an NSFetchedResultsController. I'd like to randomly insert a different type of custom cell every now and then (say, between every 10 and 20 cells), which will NOT get its data from that same database, and will be a different subclass of UITableViewCell.
I'm a little stumped on how I get in the middle of the NSFetchedResultsController and the UITableView Data Source methods. I have various options which allow the data that's pulled in to be sorted, filtered, etc., so I can't rely on using indexPath or anything like that.
What's the best approach to doing something like this? I know I can access fetchedObjects of the NSFetchedResultsController – is copying and modifying that the right way forward? Create, say, fetchedObjectWithInterstitialCells, and feed all of the Data Source and Delegate methods with the contents of that array?
Is there a better way / are there alternative ways to do it? I'll need to be able to retain the ability to sort / modify / filter the data from the database, while at all times keeping these interstitial cells at that same interval of randomly between every 10 and 20 cells.
I would consider one of the following three operations:
A: Insert objects into the database that are pulled along with the other data, but has properties to differentiate them enough to display the different subclass of the UITableViewCell. Probably the easiest way out, unless you have a very difficult datamodel.
B: If you can group your data from the data store into sections by using the sectionNameKeyPath-attribute on the NSFetchedResultsController, go for the NSFetchedResultsController + UITableViewDataSource-approach, and then return [[self.fetchedResultsController sections] count] + numberOfInterstitialCells; inside numberOfSectionsInTableView:.
In cellForRowAtIndexPath you would then need to override the section-info from the indexpath in order to switch between the right object from FetchedResultscontroller and your interstitial cells. This is probably a cumbersome and difficult way to do it, but if you are on iOS6 using parentContexts, the benefit from having implemented the NSFetchedResultsControllerDelegate is awesome
C: Fetch the objects with a normal fetchrequest and put them into a mutable array in which you insert your interstitial cells, before you load your view and feed your UITableViewDataSource with this array. As easy as option A, but you won't get the benefits of having the NSFetchedResults-Controller.

Can I use an NSDictionaryController for a dictionary of dictionaries?

I have a plist file that holds information I need to display in an app organised as a dictionary of dictionaries. I've just started programming Cocoa so am not sure the best way to go about this. Obviously I can do it all manually, and code up the loops and add the data to the UI elements, but it seems to me that bindings and the provided controllers should let me do this more easily.
I was specifically wondering if there was a direct way (e.g. using mostly Interface Builder) to link the NSDictionary I get from reading the plist file, that itself contains further NSDictionary elements, which in turn contain name-value string pairs, to an appropriate user interface element -- probably an outline view or a browser.
Alternatively, the data would fit into a function browser type panel (like in Excel) where the top level keys are categories of functions, the next level are functions in that category, and I can just populate a text area with the lowest-level details -- i.e. the value data from the final dictionary.
I don't think you are going to be able to do this with an NSBrowser or NSOutlineView. The reason I say that is because if you are using bindings with those views you need to use an NSTreeController. NSTreeController provides the ability to specify which keys in your model indicate whether or not the current object has children objects (isLeaf) and how to access the children objects (children).
So if you are going to use one of those two views, you must be able to add additional keys and properties to your model to do so. Many times when I work with NSOutlineView and NSBrowser I find it easiest to skip bindings altogether and just use the all delegate & datasource methods. They require more code but they aren't hard to put together and sometimes I prefer them to bindings if my data model is complex or if the data is not in a format that is easily pumped through an NSTreeController.
However you could use an NSTableView by doing the following.
Create an NSDictionaryController in your NIB.
In the controller that reads in your plist, create an outlet for the NSDictionaryController and hookup the outlet using Interface Builder.
In the code that reads the plist, add an additional line of code that set's the NSDictionaryController's content to the root dictionary from the plist.
In your NIB, create an NSArrayController. Bind the array controller's "Content Array" binding to the NSDictionaryController. For the "Controller Key" binding property, specify "arrangedObjects".
Now take an NSTableView and place it in your NIB. Bind each of the NSTableColumn's "Value" bindings to the NSArrayController and for the "Controller Key" binding property, specify the key from the dictionary whose value you want to display in the table column.

Adding data to a scrollview/table

I have an NSCrollView that contains an NSTableView. It has 3 columns and 4 rows. I have 4 NSStrings with content that I need to copy into the scrollview.
Using Xcode 4 I tried connecting the table or the NSTextFieldCell and then adding the text via
[_Cell1 setStringValue:MyString];
But nothing happens. It doesn't get updated.
Any way to do this?
Thank you.
EDIT:
I found the following answer to a similar question. I still am confused but after reading Apple's example about bindings I can only say that this does not make any sense, so much code to achieve something so simple. That's the problem with everything being an object and with OOP in general.
Any simple samples out there? I don't even know how to start setting this or connecting the gazillion things you need to connect to start working with this
You should use the NSTableViewDelegate. That's a set of methods the NSTableView calls to get the data that it should display. You just have to declare the delegate object of the tableview.
Delegate Protocol
NSTableView Tutorial
Unfortunately, you can't "add" or "set" the content of a table view. Like most view objects, a table view doesn't store content; it depends on a controller to provide content when it needs it.
There are two options:
Data source: simplest, easiest to understand
Binding to an array controller: harder to understand, but less work to implement
The best Apple resource on the subject: Populating Cell-Based Table Views from the Table View Programming Guide. If you're struggling, I suggest you start with the data source option. It'll be just a few lines of code, and you can adapt the simple samples from that document.
To populate the table, you need to implement these two methods:
– numberOfRowsInTableView:
– tableView:objectValueForTableColumn:row:
And to change the data, you'll need to implement one more:
- tableView:setObjectValue:forTableColumn:row:
You'll need to set your controller as the data source for the table view in interface builder. And the correct protocol for this is NSTableViewDataSource, not NSTableViewDelegate.
You could use an NSArrayController and bind the table columns' value bindings to the array controller's arranged objects. Then add the values you want to display to the array controller.

Problem retrieving NSCell data via [NSTableColumn dataCellForRow]

I am trying to retrieve a specific NSCell data from an NSTableView through [NSTableColumn dataCellForRow] but every time it shows different value for same row and same column. The data source remains the same at all time. The NSTableView is bound to an NSArrayController .Please if anyone can suggest a better way to do it correctly. And I don't want to implement those delegate methods. Let me know if you require more information.
Regards
Well, this is not a good idea to get data from a cell. Cells represent View concept in Model-View-Controller paradigm.
You should be able to access all the data that a cell can access, so get it from the primary data source.