I have a TableView with custom cells. I want a contextual menu to appear when the user right clicks (or any other Apple variants of right-click) on one of the cells (and know which cell they clicked on).
I tried to subclass NSTableView and overwrite this method:
- (NSMenu *)menuForEvent:(NSEvent *)theEvent;
But it is never being called.
On the other hand,
- (void)rightMouseDown:(NSEvent *)theEvent;
Gets called. But I'm not sure it's the one we want.
More details:
//
// PTTableView.m
//
//
// Created by Nathan Hazout on 5/31/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "PTTableView.h"
@implementation PTTableView
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
- (void)rightMouseDown:(NSEvent *)theEvent {
NSLog(@"entered rightMouseDown");
}
- (NSMenu *)menuForEvent:(NSEvent *)theEvent {
NSLog(@"entered menuForEvent");
return [super menuForEvent:theEvent];
}
- (NSView *)hitTest:(NSPoint)aPoint{
NSLog(@"entered hitTest");
return [super hitTest:aPoint];
}
- (void)dealloc
{
[super dealloc];
}
@end
rightMouseDown gets called. hiTest gets called many times. But menuForEvent doesn't.
There's no need to muck about with event handling, all you have to do to assign a contextual menu is set the table view's menu
outlet to point to the NSMenu
object that you want to use for the contextual menu.
You can do this in Interface Builder by dropping an NSMenu
object into your nib file and control-dragging from the table view to the menu to set the outlet.
Alternatively, you can use the -setMenu:
method of NSTableView
(inherited from NSResponder
) to assign the menu programmatically.
A Swift 4 version of Rob's answer:
Add the menu:
let menu = NSMenu()
menu.addItem(NSMenuItem(title: "Edit", action: #selector(tableViewEditItemClicked(_:)), keyEquivalent: ""))
menu.addItem(NSMenuItem(title: "Delete", action: #selector(tableViewDeleteItemClicked(_:)), keyEquivalent: ""))
tableView.menu = menu
The functions:
@objc private func tableViewEditItemClicked(_ sender: AnyObject) {
guard tableView.clickedRow >= 0 else { return }
let item = items[tableView.clickedRow]
showDetailsViewController(with: item)
}
@objc private func tableViewDeleteItemClicked(_ sender: AnyObject) {
guard tableView.clickedRow >= 0 else { return }
items.remove(at: tableView.clickedRow)
tableView.reloadData()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With