问题
I have a fairly vanilla Source List (dragged out from the Object Library) in my app, with an NSTreeController
as its data source. I set the NSTextField
inside the DataCell to be editable, but I want to be able to turn that off for some cells. The way I figured you would do this, is with a delegate for the NSTextField
, but none of the delegate methods I've tried get called. Is there something I'm missing? I have the delegate set with an outlet in my XIB, and it happens to be the delegate to the owner NSOutlineView
, as well, implementing both the NSOutlineViewDelegate
and NSTextFieldDelegate
protocols.
Also, I can't use the old –outlineView:shouldEditTableColumn:item:
NSOutlineViewDelegate
method either, since that only works with cell-based Outline Views (I'm assuming this is the case - the Outline View documentation doesn't appear to have been updated for Lion, though the analogous NSTableView
documentation has, and those methods don't get called either).
Update
I reproduced this in a brand new test project, so it's definitely not related to any of my custom classes. Follow the steps below to create my sample project, and reproduce this problem.
- In Xcode 4.1, create a new project, of type Mac OS X Cocoa Application, with no special options selected
- Create two new files, SourceListDataSource.m and SourceListDelegate.m, with the contents specified below
- In MainMenu.xib, drag a
Source List
onto the Window - Drag two
Object
s onto the dock (left side of the window), specifying theSourceListDataSource
class for one, and theSourceListDelegate
for the other - Connect the Outline View's
dataSource
anddelegate
outlets to those two objects - Select the Static Text
NSTextField
for the DataCell view inside the outline view's column - Turn on its
Value
binding, keeping the default settings - Connect its
delegate
outlet to the Source List Delegate object - Set its
Behavior
property to Editable - Build and Run, then click twice on either cell in the outline view.
Expected: The field is not editable, and there is a "well, should I?" message in the log
Actual: The field is editable, and no messages are logged
Is this a bug in the framework, or am I supposed to achieve this a different way?
SourceListDataSource.m
#import <Cocoa/Cocoa.h>
@interface SourceListDataSource : NSObject <NSOutlineViewDataSource>
@property (retain) NSArray *items;
@end
@implementation SourceListDataSource
@synthesize items;
- (id)init
{
self = [super init];
if (self) {
items = [[NSArray arrayWithObjects:@"Alo", @"Homora", nil] retain];
}
return self;
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
if (!item) {
return [self.items objectAtIndex:index];
}
return nil;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return !item ? self.items.count : 0;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return NO;
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
return item;
}
@end
SourceListDelegate.m
#import <Foundation/Foundation.h>
@interface SourceListDelegate : NSObject <NSOutlineViewDelegate, NSTextFieldDelegate> @end
@implementation SourceListDelegate
- (NSTableRowView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
return [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
}
- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor {
NSLog(@"well, should I?");
return NO;
}
@end
回答1:
Subclass NSTableCellView
, with an outlet for the text field, and set the text field delegate in awakeFromNib
. After doing that, control:textShouldBeginEditing:
gets called. I'm not sure why, but (edit:) if you set the delegate in the xib, the delegate methods aren't called – I had the same experience as you.
Alternatively, you can forego the delegate and conditionally set Editable using a binding, either to a boolean property of the model, or using a value transformer which acts on a model instance and returns a boolean. Use the Editable binding of the text field.
回答2:
I've encountered this problem, too. Because I didn't want to lose the bindings, I did the following:
Binding editable
of the TextField to the objectValue
and set up a custom NSValueTransformer
subclass.
来源:https://stackoverflow.com/questions/7121352/nstextfield-not-calling-delegate-when-inside-an-nstablecellview