Cocoa App NSOutlineView is not populated in Mac OS 10.10 - objective-c

My Cocoa app has a NSOutlineVew which is populated with data read from a text file and it's basically static and loaded only once in the beginning.
Prior to 10.10, the NSOutlineView works and user can drag and drop item from it to a NSTableView. However, if we run the app in 10.10, the NSOutlineView is not populated with the data and basically is just empty. There is no error message in the console log. Basically, what we found out is that the following codes are not executed in 10.10.
#pragma OutlineView for CmdSet
// Data Source methods
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return (item == nil) ? [cmdTree count] : [item numberOfChildren];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return (item == nil) ? YES : [item isExpandable];
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
return (item == nil) ? [cmdTree objectAtIndex:index] : [[item children] objectAtIndex:index];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return [item nodeName];
}
My app basically is written with AppController and I attach the code and screenshots for your reference.
#interface AppController : NSObject {
...
IBOutlet NSOutlineView *outlineViewCmdSet;
}
Can anyone point me to the correct direction how I can solve this to be able to run in both 10.10 and the prior versions? Our clients are using different Mac OS. It's good to be able to support all of the OSes.
The OutLine View in Interface Builder

Related

NSOutlineView, setFloatsGroupRows: not working

I know it should work, I can see it in sample projects, but in my sample project I can't force outline view to float group rows. The code is straightforward, everything works except that feature. Probably I'm missing something obvious.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self.outlineView setFloatsGroupRows:YES];
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
if (item == nil)
return [#[#"1", #"2",#"3",#"4",#"5"] objectAtIndex:index];
return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
return NO;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
if (item == nil)
return 5;
return 0;
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
return item;
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:[tableColumn identifier] owner:self];
return tableCellView;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
{
if ([#[#"1", #"2",#"3",#"4",#"5"] indexOfObject:item] == 0)
return YES;
return NO;
}
Edit I added NSTableView alongside NSOutlineView to my project, added the same datasource and delegate methods and table view's group row flows, when outline view's one still doesn't. I'm wondering what I am missing, why outline view's group row doesn't want to fly?..
Solved. In NSOultineView group rows float only over its child rows. They don't float over other non group rows but NSTableView does. So if you have a group row without child items like in my example then it won't float.
In my opinion it's a bug or at least there shoud be an option for both cases (for at least a consistency with a table view behaviour).
Make sure self.outlineView IBOutlet is connected to the NSOutlineView in the xib.

NSButtonCell checkbox inside NSTableView is always getting NSOffState. Why?

Hi guys I'm new to Cocoa programming and I am getting always NSOffState whether I'm checking or unchecking an NSButtonCell (Check Box Cell in the UI dragged to a cell in an NSTableView).
I have a #property IBOutlet NSButtonCell *mySelection, connected to the respective UI and the following code.
- (void) tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
MediaAComparar *media = [mediasRecesEnStock objectAtIndex:row];
NSString *identifier = [tableColumn identifier];
if ([identifier isEqualToString:#"seleccion"])
{
if ([mySelection state] == NSOnState)
{
[media setValue:object forKey:#"seleccion"];
NSLog(#"on state");
}
if ([mySelection state] == NSOffState)
{
[media setValue:object forKey:#"seleccion"];
NSLog(#"off state");
}
}
}
I never get the NSOnState to execute, the only NSLog message I get is: off state.
Can anyone give me some help?
Thanks!!
If you have one outlet ("mySelection") and multiple rows, which row did you think the outlet connects to? (Answer: none of them. You probably hooked it up to the prototype cell, which is never displayed or used directly.)
But no matter, you don't need to check the state before you set it. Assuming your other code is correct, you should be able to do something like:
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
MediaAComparar *medium = [mediasRecesEnStock objectAtIndex:row];
if ([tableColumn.identifier isEqualToString:#"seleccion"])
medium.seleccion = object.booleanValue;
}
Less code is better code.

Little circle-line bar stuck at top of NSOutlineView when rearranging using drag and drop

I've got NSOutlineView that, at the moment, only lists children of the root item. Everything works except when I try to rearrange items using drag & drop. The line with the circle in front of it always stays above the top row and doesn't follow my items when they need to be dragged between other items. However, I still get the index positions properly so I can still rearrange them in the datasource properly. I don't want to rearrange items by dragging them onto each other, I only want to rearrange the items off the root level (like the VLC playlist on the Mac).
Here are my four required methods:
//queue is a C-based data structure
-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
if(item == nil){
return queue.count; //each list item
}else{
return 0; //no children of each list item allowed
}
}
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
if(item != nil) return nil;
return [[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithLong:index],#"index",
[NSString stringWithFormat:#"%s",queue.item[index].filepath],#"filePath",
nil] copy];
}
-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
if(item == nil){
return YES;
}else{
return NO;
}
}
-(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
if(item == nil) return nil;
return [item objectForKey:[tableColumn identifier]];
}
And my drag methods:
-(BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard
{
[pasteboard declareTypes:[NSArray arrayWithObject:LOCAL_REORDER_PASTEBOARD_TYPE] owner:self];
[pasteboard setData:[NSData data] forType:LOCAL_REORDER_PASTEBOARD_TYPE];
return YES;
}
-(NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
{
NSUInteger op = NSDragOperationNone;
if(index != NSOutlineViewDropOnItemIndex){
op = NSDragOperationMove;
}
return op;
}
I'm kind of confused about what desired behavior you want. Does this sample project achieve the desired drag and drop highlighting behavior (it shows the o–––––– indicator between each row, which is how VLC appears to work here for me):
http://www.markdouma.com/developer/NSOutlineViewFinagler.zip
(Note that it doesn't include code yet to actually carry through the reordering of the items).
If not, can you describe again what it currently does now and what you want it to do?
Also, you didn't include code for it here, but did you make sure to register the outline view for the LOCAL_REORDER_PASTEBOARD_TYPE drag type? I would do it in awakeFromNib:
- (void)awakeFromNib {
[self.outlineView registerForDraggedTypes:#[LOCAL_REORDER_PASTEBOARD_TYPE]];
}
That's necessary for the outline view to allow itself to be a drag destination.

why objectValueForTableColumn is called so many times for outlineView?

I'm learning outline view of cocoa by Apple OS x developer library. The example source is like this:
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
return (item == nil) ? [FileSystemItem rootItem] : [(FileSystemItem *)item childAtIndex:index];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return (item == nil) ? YES : ([item numberOfChildren] != -1);
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return (item == nil) ? 1 : [item numberOfChildren];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return (item == nil) ? #"/" : [item relativePath];
}
This will list all files in my system like a tree.
The question is:
1. if there are 32 files under the "/", the method
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
will be called 62 times, I don't know why?
2. the method
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
doesn't have a parameter about the row, then how the cocoa to determine which row the item should be displayed?
if there are 32 files under the "/", the method
(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
will be called for each row and column as it is displayed. I assume you have 2 columns and 31 rows are actually shown.
the method doesn't have a parameter about the row, then how the cocoa to determine which row the item should be displayed?
The item is a pointer to the object used to populate the table. This is all the NSOutlineViewDataSource Protocol needs to know. Details of displayed rows in internal to the NSOutlineView

Changing view for selected in view-based NSTableView

How do I change the view for the selected row when using a view-based NSTableView? Specifically, I'd like to have a simple NSView subclass for unselected rows and a more complex NSView subclass for the selected row which allows editing of more information associated with the row item.
An example is the way Things allows you to expand the item being edited as seen here: http://culturedcode.com/things/
My guess is that you want to use a different NSTableCellView subclass when the row is selected. I think you should be able to do something like this:
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSTableView *table = [notification object];
NSIndexSet *allColumns = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [[table tableColumns] count])];
[table reloadDataForRowIndexes:[table selectedRowIndexes] columnIndexes:allColumns];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if ([[tableView selectedRowIndexes] containsIndex:row])
{
// If the row is selected, return an instance of the class for selected views
SelectedTableCellView *selectedView = ...; // Get from makeViewWithIdentifier:
// Set up selectedView
return selectedView;
}
else
{
NonSelectedTableCellView *nonSelectedView = ...; // Get from makeViewWithIdentifier:
// Set up nonSelectedView
return nonSelectedView;
}
}
It might be nice if you elaborated a little bit more on what you mean by "change the view to a more complex view"
Nonetheless, you could for instance, implement - (void)tableViewSelectionDidChange:(NSNotification *)notification in the delegate of the table view, get the selected NSTableRowView if it is visible, and change it in what way you want, which includes making it more complex, expanding it (see below), etc.
To modify the size of a row, you would need to implement - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row in the same delegate, and call the table view's -noteHeightOfRowsWithIndexesChanged to update the height for particular rows.
I think the app is created by NSOutlineView in outlineview only you can easily expand your selected row...
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
if ([item isKindOfClass:[NSDictionary class]])
{
return YES;
}else
{
return NO;
}
}
I think this way is write..