I'm creating an NSTableView programatically. numberOfRowsInTableView is the only method that gets called when I assign the delegate and dataSource. The NSTableView remains blank and empty. What am I doing wrong?
in myDocument.m:
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
NSTableView *tableView = [NSTableView alloc] initWithFrame:CGRectMake(0,0,400,400)];
// I've tried putting the delegate before the datasource. No change.
tableView.dataSource = self;
tableView.delegate = self;
// I've tried adding the table before assigning the delegate/datasource. No change.
[aController.window.contentView addSubview:tableView];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSLog(#"making view for table...");
NSBox *box = [[NSBox alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
box.borderColor = [NSColor blackColor];
box.borderWidth = 10;
return box;
}
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
NSLog(#"getting data...");
return #{ #"myKey": #"myValue" };
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
NSLog(#"getting count...");
return 2;
}
numberOfRowsInTableView is the only thing that get's called. Why? How can I fix this?
You table view doesn't contain any columns and therefore doesn't call the viewForColumn: delegate method.
Replace your initialization code in windowControllerDidLoadNib with the following and your delegate methods will get called:
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
NSTableView *tableView = [[NSTableView alloc] initWithFrame:CGRectMake(0,0,400,400)];
[tableView addTableColumn:[[NSTableColumn alloc] initWithIdentifier:#"MyColumn"]];
tableView.dataSource = self;
tableView.delegate = self;
[aController.window.contentView addSubview:tableView];
}
Probably you can use Interface Builder to configure & layout your tableview.
Related
The NSButtonCell from the code bellow works fine, but it doesn't visualy display the check icon when clicked. Any ideas why?
- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if ([[tableColumn identifier] isEqualToString:#"select"]) {
NSButtonCell *cell = [[NSButtonCell alloc]init];
[cell setButtonType:NSSwitchButton];
[cell setTarget:self];
[cell setAction:#selector(checkboxChanged:)];
[cell setTitle:#""];
return cell;
} else {
NSCell *cell = [tableColumn dataCell];
return cell;
}
}
Here is the action code:
- (IBAction)checkboxChanged:(id)sender {
NSButtonCell *aCell = [[sender tableColumnWithIdentifier:#"select"]
dataCellForRow:[sender selectedRow]];
if ([aCell state] == NSOnState) {
NSLog(#"ON");
[aCell setState:NSOffState];
} else {
NSLog(#"OFF");
[aCell setState:NSOnState];
}
}
I'm not sure why your first solution didn't work—maybe you didn't have your delegate hooked up? Note that the data source and the delegate are two separate things.
The method you implemented in your answer, which is a data source, is not the proper place to do that. The data source, and particularly numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:, should only return the content being presented, not create view/cell objects.
I recommend creating and configuring the NSButtonCell in your xib, if you have one, or in the same place where you create your table view and its columns—that's also the correct place to set each column's cell.
I solved this problem by changing the above code from the NSOutlineView delegate method outlineView: dataCellForTableColumn:item: to the delegate method outlineView: objectValueForTableColumn: byItem:
Like so:
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
if ([[tableColumn identifier] isEqualToString:#"select"]) {
NSButtonCell* cell = [tableColumn dataCell];
[cell setSelectable:YES];
[cell setEnabled:YES];
[cell setTransparent:NO];
[cell setButtonType:NSSwitchButton];
[cell setTarget:self];
[cell setAction:#selector(checkboxChanged:)];
[cell setTitle:#""];
return cell;
}
return nil;
}
And now it works perfectly.
I created a custom cell and upon click, it should display a popup.
However, when this is works successfully, it seems to create an issue where I am not able to click the delete button.
It seems that my UITapRecognizer supercedes my method to delete.(Means the popup is displayed instead when I click the delete button )
Any idea how to solve this?
Below is my code to handle tap in the cell (OfficeCell.m)
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(openOfficePopover)];
[tapGestureRecognizer setNumberOfTapsRequired:1];
[self setUserInteractionEnabled:YES];
[self addGestureRecognizer:tapGestureRecognizer];
self.textLabel.font = [UIFont boldSystemFontOfSize:15];
self.textLabel.textColor = mRgb(0x3a, 0x6c, 0x99);
}
return self;
}
Below is my code to handle the delete in the ViewController :
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
NSInteger section = [indexPath section];
if (section ==1 )
{
return YES;
}
return NO;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source
NSInteger section = [indexPath section];
if(section == 1)
{
[_sectionOffice removeObjectAtIndex:indexPath.row];
}
[self.formView reloadData];
}
}
Just realize that the fix should be really simple :
changing 2 lines of code solve the issue :
From :
[self setUserInteractionEnabled:YES];
[self addGestureRecognizer:tapGestureRecognizer];
To :
[self.contentView setUserInteractionEnabled:YES];
[self.contentView addGestureRecognizer:tapGestureRecognizer];
I'm trying to show some content in my NSTableView in my mac app.
#implementation OpenTasksViewController {
NSMutableArray *tasks;
}
- (id)init {
self = [super init];
if (self) {
tasks = [NSMutableArray array];
[tasks addObject: [[Task alloc] initWithTitle:#"HI"]];
}
return self;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [tasks count];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTableCellView *cell = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
Task *t = [tasks objectAtIndex:row];
cell.textField.stringValue = t.title;
return cell;
}
This class implements the NSTableViewDataSource and NSTableViewDelegate protocols.
Sadly, my app doesn't show the content.
I tried using reloadData, but that didn't work either.
When I debug into the project, the stringValue of cell.textField is correct.
I would like to create an NSTableview with custom NSTableCellViews.
Here is what I have right now:
A nib file for the cell (view nib) called CustomCell.xib
A custom class for my cell called CustomCell
And the code in my AppDelegate.m:
Here I create my table view programmatically:
NSScrollView *tableContainer = [[NSScrollView alloc]initWithFrame:NSMakeRect(self.window.frame.size.width-TABLEWIDTH, 0, TABLEWIDTH, self.window.frame.size.height)];
NSTableView *tableView = [[NSTableView alloc] initWithFrame:NSMakeRect(self.window.frame.size.width-TABLEWIDTH, 0, TABLEWIDTH, self.window.frame.size.height)];
NSTableColumn *firstColumn = [[[NSTableColumn alloc] initWithIdentifier:#"firstColumn"] autorelease];
[[firstColumn headerCell] setStringValue:#"First Column"];
[tableView addTableColumn:firstColumn];
tableView.dataSource = self;
tableView.delegate = self;
[tableContainer setDocumentView:tableView];
tableContainer.autoresizingMask = NSViewHeightSizable | NSViewMinXMargin;
[self.window.contentView addSubview: tableContainer];
And here is the delegate method where I would like to put my custom cell code:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// In IB the tableColumn has the identifier set to the same string as the keys in our dictionary
NSString *identifier = [tableColumn identifier];
if ([identifier isEqualToString:#"myCell"]) {
// We pass us as the owner so we can setup target/actions into this main controller object
CustomCell *cellView = [tableView makeViewWithIdentifier:identifier owner:self];
// Then setup properties on the cellView based on the column
cellView.textField.stringValue = #"Name";
return cellView;
}
return nil;
}
In the nib file for my custom cell I have hooked up the cell view with my custom class called CustomCell which subclasses NSTableCellView. I have not done any other steps as for now. So my CustomCell.m is just default initialization code. I haven't touched it. And I did not do anything else in my nib file, so I did not change file's owner or anything like that because I don't really know what to do.
Can anyone help out ? I looked at sample files from the Apple documentation, but after days of researching I have not found any solutions. I would really appreciate if you could help me.
This is what I ended up doing :
Of course you have to subclass NSTableCellView and return it like I did below. If you are familiar with table views in iOS you should be familiar with methods like:
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
//this will be called first. It will tell the table how many cells your table view will have to display
return [arrayToDisplay count];
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
//this is called after the count of rows is set. It will populate your table according to the data your array to display contains
[tableView setTarget:self];
[tableView setAction:#selector(click)];
NSString *identifier = [tableColumn identifier];
if ([identifier isEqualToString:#"TheCell"]) {
CustomCell *cellView = [tableView makeViewWithIdentifier:identifier owner:self];
cellView.cellText.stringValue = [arrayToDisplay objectAtIndex:row];
return cellView;
}
return nil;
}
And the click method that is triggered when a row is selected would look like this:
-(void)click{
int index = [table selectedRow];
// Do something with your data
//e.g
[[arrayToDisplay objectAtIndex:index] findHiggsBoson];
}
And something that has to be added to the NSTableView:
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:#"column"];
column.width = self.frame.size.width;
[tableView addTableColumn:column];
You do not need to subclass NSTableView to have custom NSTableViewCell subclasses.
You might consider using a view-based Table View also...
Hi I am using a searchDisplayController to filter through my search results. My code snippet is as follows:
- (void)viewDidLoad
{
[super viewDidLoad];
//Set up search bar
UISearchBar *tempBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0,0,320,40)];
self.sBar = tempBar;
[tempBar release];
self.sBar.delegate = self;
self.sBar.tintColor = [UIColor colorWithHexString:#"#b6c0c7"];
self.sBar.placeholder = #"Search Questions and Topics";
[self.view addSubview:sBar];
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:sBar contentsController:self];
[self setSearchDisplayController:searchDisplayController];
[searchDisplayController setDelegate:self];
[searchDisplayController setSearchResultsDataSource:self];
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm)
{
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
[self.resultTableView reloadData];
self.resultTableView.scrollEnabled = YES;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"zzz");
}
Do I need to setup anything in my view did load to trigger the uitable delegate method?
Note that I have already declared UISearchDisplayDelegate, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate in my .h files. Also my tableView cellForRowAtIndexPath method is working.
Have you actually set
self.tableView.delegate = self
or connected it up in Interface Builder