【问题标题】:How do I bind programmatically in the view subclass of my NSCollectionView?如何在 NSCollectionView 的视图子类中以编程方式绑定?
【发布时间】:2009-07-31 02:16:02
【问题描述】:

我已经成功地创建了一个 NSCollectionView 并向 IB 中的视图原型添加了一个标签,该标签绑定到我所表示的对象的一个​​属性。我现在想以编程方式创建一个 NSButton 和 NSTextField,其中 NSTextField 绑定到我表示的对象的属性。单击按钮时,我想显示和隐藏 NSTextField。

我遇到的问题是,如果我将控件的初始化代码放在视图的 initWithCoder 方法中,并将绑定放在视图的 awakeFromNib 中,则绑定不会被连接起来。如果我将控件的初始化放在 awakeFromNib 中,当单击按钮时,我无法访问视图中的控件(使用 NSLog 打印出来时它们为空)。

据我所知,问题可能在于 NSCollectionView 的工作方式是,它创建视图的一个实例,然后根据集合视图中的每个对象的多少复制它。如何获取要初始化的按钮以及与原型副本一起使用的绑定?

下面是我的初始化代码和我在子类视图的 awakeFromNib 中的绑定:

子视图.h

@interface SubView : NSView {
    NSButton *button;
    NSTextField *textField;
    IBOutlet NSCollectionViewItem *item; // Connected in IB to my NSCollectionViewItem
}

- (IBAction)buttonClicked:(id)sender;

@end

子视图.m

@implementation SubView

- (id)initWithCoder:(NSCoder *)decoder
{
    id view = [super initWithCoder:decoder];

    button = [[NSButton alloc] initWithFrame:NSMakeRect(50, 95, 100, 20)];
    [button setTitle:@"Begin Editing"];
    [button setTarget:self];
    [button setAction:@selector(buttonClicked:)];
    [self addSubview:button];

    textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 100, 75)];
    [self addSubview:textField];

    return(view);
}

- (void)awakeFromNib
{   
        // Bind the textField to the representedObject's name property
        [textField bind:@"value" 
       toObject:item 
        withKeyPath:@"representedObject.name" 
        options:nil];
}

- (IBAction)buttonClicked:(id)sender
{
    [button setTitle:@"End Editing"];
    [textField setHidden:YES];
}

@end

【问题讨论】:

    标签: objective-c cocoa binding nscollectionview


    【解决方案1】:

    这听起来和我刚刚做的很相似,所以也许这就是你需要的。

    子类NSCollectionView 并覆盖:

    - (NSCollectionViewItem *)newItemForRepresentedObject:(id)object
    

    newItemForRepresentedObject: 中,检索视图项,然后添加您的控件和任何编程绑定:

    @implementation NSCollectionViewSubclass
    
    - (NSCollectionViewItem *)newItemForRepresentedObject:(id)object {
    
        // Allow the superclass to create or copy the collection view item
        NSSCollectionViewItem *newItem = [super newItemForRepresentedObject:object];
    
        // Get the new item's view so you can mess with it
        NSView *itemView = [newItem view];
    
        //
        // add your controls to the view here, bind, etc
        //
    
        return newItem;
    }
    
    @end
    

    希望这是靠近你需要去的地方......

    【讨论】:

      【解决方案2】:

      -awakeFromNib 不会在 NSCollectionViewItem 的视图上调用,如果该视图与 NSCollectionView 位于同一 nib 中,但如果您将视图放在单独的 nib 中,则会调用它。

      • 创建一个空的 nib 文件 (BlahBlahCollectionViewItem.nib)。
      • 从您拥有的任何 nib 中剪切集合项目视图
      • 将其粘贴到新的 nib 文件中
      • 将其所有者的类更改为 NSCollectionViewItem。
      • 将所有者的视图出口连接到新粘贴的视图
      • 打开包含 NSViewController 的 nib 文件
      • 选择关联的 NSViewControllerItem
      • 将其 Nib Name 属性更改为新 nib 的名称
      • 将您的代码保存在-awakeFromNib

      【讨论】:

        【解决方案3】:

        -awakeFromNib 不会为从原型 NSCollectionViewItem 复制的视图调用。把你的绑定代码放在initWithCoder:,应该没问题。

        【讨论】:

        • 对,当我尝试将绑定代码放入 initWithCoder 时:我收到此错误:引发未捕获的异常控制器不能为零 *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因: 'Controller cannot be nil' 我认为这是因为 initWithCoder 中尚未连接“item”属性(CollectionViewItem 的 IB 插座)。还有其他方法可以到达代表对象吗?
        • 嗯..好点。可能您最好的解决方法是将绑定代码放在另一个方法中,然后使用 -performSelector:withObject:afterDelay:0.0 调用它。它不漂亮,但它应该可以工作,因为我认为没有其他选择。
        • 我尝试使用我的 initWithCoder 中的 performSelector:withObject:afterDelay 调用绑定代码,但问题是先调用 initWithCoder,然后调用 awakeFromNib,然后为每个集合视图项调用 initWithCoder。您能否修改您的答案以显示您认为应该有效的绑定代码?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-14
        • 2019-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多