我正在尝试实现一些应该简单且相当常见的东西:在绑定中填充NSPopupButton中的NSPopupButton填充NSTableView。 Apple在其文档Implementing To-One Relationships Using Pop-Up Menus中为基于单元格的表描述了这一点,它看起来像这样:
我无法让这个用于基于视图的表。无论我做什么,“作者”弹出窗口都不会填充。
我有两个阵列控制器,一个用于表格中的项目(项目),另一个用于作者(作者),两者都与我的相应实体相关联核心数据模型。我在我的单元格中绑定NSManagedPopup,如下所示:在界面构建器中:
如果我把弹出窗口放在桌子外的某个地方它工作正常(显然除了选择),所以我想绑定设置应该没问题。
有人向作者数组控制器建议workaround using an IBOutlet property,但这似乎对我不起作用。
在another SO question中,建议子类化NSTableCellView并以编程方式建立所需的连接。我试过这个,但收效甚微。
如果我按如下方式设置绑定:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
if ([tableColumn.identifier isEqualToString:@"Author") {
AuthorSelectorCell *authorSelectorCell = (AuthorSelectorCell *)view;
[authorSelectorCell.popupButton bind:NSContentBinding toObject:self.authors withKeyPath:@"arrangedObjects" options:nil];
[authorSelectorCell.popupButton bind:NSContentValuesBinding toObject:self.authors withKeyPath:@"arrangedObjects.name" options:nil];
[authorSelectorCell.popupButton bind:NSSelectedObjectBinding toObject:view withKeyPath:@"objectValue.author" options:nil];
}
return view;
}
弹出窗口确实显示了可能的作者列表,但当前选择始终显示为“无值”。如果我添加
[authorSelectorCell.popupButton bind:NSSelectedValueBinding toObject:view withKeyPath:@"objectValue.author.name" options:nil];
当前选择完全为空。显示当前选择的唯一方法是设置
[authorSelectorCell.popupButton bind:NSSelectedObjectBinding toObject:view withKeyPath:@"objectValue.author.name" options:nil];
一旦我选择其他作者就会中断,因为它会尝试将NSString*
分配给Author*
属性。
任何想法?
答案 0 :(得分:8)
我遇到了同样的问题。我已经放了一个sample project表明这可以在Github上使用。
有人向作者提出了使用IBOutlet属性的解决方法 数组控制器,但这似乎对我不起作用。
这是 为我工作的方法,并在sample project中进行了演示。这个难题的缺失是,数组控制器的IBOutlet需要在提供TableView委托的类中。
答案 1 :(得分:0)
遇到同样的问题并发现this workaround - 基本上将你的作者数组控制器从带有IBOutlet的nib中取出并通过文件所有者绑定到它。
答案 2 :(得分:0)
您可以尝试NSPopUpbutton的这四个设置:
在我的例子中,“allPersons”相当于你的“作者”。 我在文件所有者中将allPersons作为属性(NSArray *)提供。
此外,我将tableView委托绑定到File的所有者。如果没有绑定,我只会得到一个默认列表:Item1,Item2,Item3
答案 3 :(得分:0)
我总是更喜欢程序化方法。在NSTableCellView上创建一个类别:
+(instancetype)tableCellPopUpButton:(NSPopUpButton **)popUpButton
identifier:(NSString *)identifier
arrayController:(id)arrayController
relationship:(NSString *)relationshipName
relationshipArrayController:(NSArrayController *)relationshipArrayController
relationshipAttribute:(NSString *)relationshipAttribute
relationshipAttributeIsScalar:(BOOL)relationshipAttributeIsScalar
valueTransformers:(NSDictionary *)valueTransformers
{
NSTableCellView *newInstance = [[self alloc] init];
newInstance.identifier = identifier;
NSPopUpButton *aPopUpButton = [[NSPopUpButton alloc] init];
aPopUpButton.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[aPopUpButton bind:NSContentBinding //the collection of objects in the pop-up
toObject:relationshipArrayController
withKeyPath:@"arrangedObjects"
options:nil];
NSMutableDictionary *contentBindingOptions = [NSMutableDictionary dictionaryWithDictionary:[[TBBindingOptions class] contentBindingOptionsWithRelationshipName:relationshipName]];
NSValueTransformer *aTransformer = [valueTransformers objectForKey:NSValueTransformerNameBindingOption];
if (aTransformer) {
[contentBindingOptions setObject:aTransformer forKey:NSValueTransformerNameBindingOption];
}
[aPopUpButton bind:NSContentValuesBinding // the labels of the objects in the pop-up
toObject:relationshipArrayController
withKeyPath:[NSString stringWithFormat:@"arrangedObjects.%@", relationshipAttribute]
options:[self contentBindingOptionsWithRelationshipName:relationshipName]];
NSMutableDictionary *valueBindingOptions = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSAllowsEditingMultipleValuesSelectionBindingOption,
[NSNumber numberWithBool:YES], NSConditionallySetsEditableBindingOption,
[NSNumber numberWithBool:YES], NSCreatesSortDescriptorBindingOption,
[NSNumber numberWithBool:YES], NSRaisesForNotApplicableKeysBindingOption,
[NSNumber numberWithBool:YES], NSValidatesImmediatelyBindingOption,
nil];;
@try {
// The object that the pop-up should use as the selected item
if (relationshipAttributeIsScalar) {
[aPopUpButton bind:NSSelectedValueBinding
toObject:newInstance
withKeyPath:[NSString stringWithFormat:@"objectValue.%@", relationshipName]
options:valueBindingOptions];
} else {
[aPopUpButton bind:NSSelectedObjectBinding
toObject:newInstance
withKeyPath:[NSString stringWithFormat:@"objectValue.%@", relationshipName]
options:valueBindingOptions];
}
}
@catch (NSException *exception) {
//NSLog(@"%@ %@ %@", [self class], NSStringFromSelector(_cmd), exception);
}
@finally {
[newInstance addSubview:aPopUpButton];
if (popUpButton != NULL) *popUpButton = aPopUpButton;
}
return newInstance;
}
+ (NSDictionary *)contentBindingOptionsWithRelationshipName:(NSString *)relationshipNameOrEmptyString
{
NSString *nullPlaceholder;
if([relationshipNameOrEmptyString isEqualToString:@""])
nullPlaceholder = NSLocalizedString(@"(No value)", nil);
else {
NSString *formattedPlaceholder = [NSString stringWithFormat:@"(No %@)", relationshipNameOrEmptyString];
nullPlaceholder = NSLocalizedString(formattedPlaceholder,
nil);
}
return [NSDictionary dictionaryWithObjectsAndKeys:
nullPlaceholder, NSNullPlaceholderBindingOption,
[NSNumber numberWithBool:YES], NSInsertsNullPlaceholderBindingOption,
[NSNumber numberWithBool:YES], NSRaisesForNotApplicableKeysBindingOption,
nil];
}