Subclass NSTableRowView for NSOutlineView - macos

If you have a tableView and want to use a subclass of NSTableRowView, you can use the delegate function - (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row. Any ideas of how I can do this with an NSOutlineView (without subclassing NSOutlineView)?

The NSOutlineView has this delegate method:
(NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item
that serves the same purpose for an outline view. I don't see this method in my docs in Xcode, but it's declared in NSOutlineView.h in MacOSX10.7.sdk

Related

UITableView custom cell not displaying data

Here is the story. I have a simple app in which I use 2 tabs, both of them with UITableView. The first tab/view is called "Favorites" and the second one is called "My Profile." In addition I have a custom UITable cell named "CustomViewCell.xib" with an identifier of the same name. FavoritesViewController is a subclass of UITableViewController and that one is running perfectly. But for the ProfileViewController I am using normal ViewController because I don't want the whole view to be UitableView. To make that possible, I the following to ProfileViewController.h:
#interface ProfileViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) IBOutlet UITableView *tableView;
then in the viewDidLoad of ProfleViewController.m file I have:
[self.tableView registerNib:[UINib nibWithNibName:#"CustomViewCell" bundle:nil]
forCellReuseIdentifier:#"CustomViewCell"];
The following methods are implemented just as in the other tab that's working:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.myArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Here I am customizing the cell and returning it.
}
When i run the app, the cells are the right height, but are empty.
To debug I put a break point right before cellForRowAtIndexPath, and the app runs without an error which it shouldn't. So, the program is not even getting to this method. So, I think that's the reason the cells are empty. Do you guys have any idea what might be causing it to skip this particular method? can you also explain it in simpler terms because I'm newbie, you know?
In you ViewDidLoad method, add this code:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
Then check again if the breakpoint works
Have you implemented a UITableViewDataSource? A UITableViewController is the delegate and datasource for the Table View it manages so you can define all those methods in the View Controller itself.
For a UITableView that is a subview of a UIViewController, you need to define the Table View's delegate and datasource.
See here: http://www.aboveground.com/tutorials/adding-a-uitableview-to-a-custom-uiview

How call a method when a UICollectionViewCell is pressed?

I'm trying to call another UIViewController when a UICollectionViewCell is pressed, but I just can't. Which one of the following method i should use?
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
}
-(void) collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
}
Just link the UICollectionViewCell to a new view controller in storyboard!
You don't need those methods.
In a simple case you may want to use a storyboard and establish a segue from your cell to another viewcontroller. That would work if you want to link every cell to the same view controller class.
If you need to instantiate view controllers of different classes or if you are not using a storyboard then you will use first function you mentioned
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

NSTableView: only numberOfRowsInTableView: datasource is called

I met a problem about the NSTableView, and it is like:
one datasource of tableview is called:
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return [self.dataArray count];
}
But this one is never called:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
// the code
}
I have checked the the array really had data, and also checked the
[NSTableView reloadData] was called in the main thread.
SO I'm totally lost about this weird problem.
Would any one give some tips?
thanks!
I moved the initial code from awakeFromNib to the init, and it called correctly. But I still don't know the real reason. I guess it matters with the life-cycle of the view because the class which has the tableview is a subclass of NSObject and not of NSViewController.

view-based NSTableView's views from XIB?

Is it possible to have a separate XIB file for the NSTableCellView of a view-based NSTableView? Maybe with the help of a NSViewController?
Yes, it seems to be possible.
From Apple's documentation:
In order to function, a programmatically implemented view-based table must implement the following:
...
The - (NSView *)tableView:viewForTableColumn:row: method that is defined by the NSTableViewDelegate Protocol. This method both provides the table with the view to display as the cell for the specific column and row, as well as populates that cell with the appropriate data.
This way you can have an object of the class NSView (or any subclass) and give it back, after you properly filled it with data. Where you get this object from, is not of interest. As far as I know, it would be possible to do the following, for example:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Assume you have a XIB called View.xib
[NSBundle loadNibNamed:#"View" owner:self];
// And you have an IBOutlet to your NSTableView (that's view based) called tView
[tView reloadData];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return 20;
}
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
// Assume your class has an IBOutlet called contentOfTableView,
// your class is File's Owner of the View.xib and you connected the outlet.
return contentOfTableView;
}
Hope it works. I just threw it together having a rough idea in mind. Good luck!

NSOutlineView outlineViewSelectionDidChange

my NSOutlineView outlineViewSelectionDidChange method will not be called.
I set set the NSOutlineViews delegate to the class where the other methods such as
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
exist. But outlineViewSelectionDidChange will not be called on selecting an item.
Does anybody has an idea?
This notification is a bit odd, in that it is not automatically forwarded to delegates. Try adding an explicit registration to your initialization code, like this example:
- (void)windowControllerDidLoadNib:(NSWindowController *)aController;
{
[super windowControllerDidLoadNib:aController];
NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:#selector(outlineViewSelectionDidChange:)
name:#"NSOutlineViewSelectionDidChangeNotification"
object:outlineView];
}
Okay,
meanwhile i figured out that the "NSOutlineViewSelectionDidChangeNotification" will be thrown only within the notification object. So i had to subclass my NSOutlineView to catch the notification and pass it to the object where i need it.
Your own view needs to conform to the NSOutlineViewDelegate protocol like so..
#interface MyOutlineViewController : NSView <NSOutlineViewDataSource,NSOutlineViewDelegate> {
IBOutlet NSOutlineView *myoutlineview;
}
#end
you will have this methods in your implementation
-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item;
-(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
where you setup your outlineview.
When loading this view -(void)viewDidLoad gets called and your predefined nib/xib file or your manual call will set your datasource to fill it depending on your logic.
Now in your -(void)viewDidLoad your myoutlineview needs to set its own delegate with
[myoutlineview setDelegate:self];
so your own View may know where to call its notification methods triggerd from selections and so on. So you can place your notification logic inside the same View class conforming to this protocol.
-(void)outlineViewSelectionDidChange:(NSNotification *)notification {
NSLog(#"selection did change");
}

Resources