Cocoa 基于视图的NSTableView中的NSPoupButton:使绑定正常工作 问题描述

Cocoa 基于视图的NSTableView中的NSPoupButton:使绑定正常工作 问题描述,cocoa,nstableview,cocoa-bindings,nspopupbutton,Cocoa,Nstableview,Cocoa Bindings,Nspopupbutton,我正在尝试实现一些简单且相当常见的功能:在bindings-populated NSTableView中有一个bindings-PopupButton。Apple在其文档中对基于单元格的表进行了描述,如下所示: 对于基于视图的表,我无法使其工作。无论我做什么,“作者”弹出窗口都不会自行填充 我有两个数组控制器,一个用于表中的项(项),另一个用于作者(作者),两者都与核心数据模型中的相应实体关联。我在interface builder中将NSManagedPopup绑定到我的单元格中,如下所示:

我正在尝试实现一些简单且相当常见的功能:在bindings-populated NSTableView中有一个bindings-PopupButton。Apple在其文档中对基于单元格的表进行了描述,如下所示:

对于基于视图的表,我无法使其工作。无论我做什么,“作者”弹出窗口都不会自行填充

我有两个数组控制器,一个用于表中的项(),另一个用于作者(作者),两者都与核心数据模型中的相应实体关联。我在interface builder中将NSManagedPopup绑定到我的单元格中,如下所示:

  • 内容->作者(控制器键:arrangedObjects)
  • 内容值->作者(控制器键:arrangedObjects,模型键路径:name)
  • 所选对象->表格单元格视图(模型键路径:objectValue.author
如果我把弹出窗口放在表外的某个地方,它就可以正常工作(除了明显的选择),所以我想绑定设置应该可以


我已经尝试过的事情
  • 有人向作者数组控制器推荐了一个新的控制器,但这似乎对我也不起作用

  • 在年,有人建议将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*
    属性


  • 有什么想法吗?

    也有同样的问题并发现了-基本上是用一个IBOutlet将您的作者数组控制器从nib中取出,并通过文件所有者绑定到它。

    我也有同样的问题。我已经在Github上展示了这是可能的

    有人向作者建议了一种使用IBOutlet属性的变通方法 阵列控制器,但这似乎对我也不起作用


    这是对我有效的方法,如中所示。谜题中缺少的一点是,阵列控制器的IBOUTLE必须位于提供TableView委托的类中。

    您可以尝试NSPopUpbutton的这四个+1设置:

    在我的例子中,“所有人”等同于您的“作者”。 我在文件所有者中有所有可用的人员作为财产(NSArray*)

    此外,我将tableView委托绑定到文件的所有者。如果没有绑定,我只会得到一个默认列表:Item1、Item2、Item3


    我总是喜欢编程方法。在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];
    }
    

    你找到解决方案了吗?我也有同样的问题。哦,老兄,这让我非常疯狂,谢谢你的解决方案。绑定到我文件所有者的数组控制器IBOutlet(而不是同一nib中的数组控制器对象!)工作正常。给我留下深刻印象的是,有人提交过雷达吗?感谢你引导我找到解决方案。另一个关键信息是将弹出窗口的选定对象绑定到表格单元格视图(Model key Path=objectValue.propertyName);这在最初的问题中提到过,但大多数教程似乎没有充分强调这一点。(苹果的文章确实提到了这一点,但没有提到弹出菜单。)