我正在使用NSCollectionView
来显示各种对象。除了一件烦人的事情外,整件事情都运作良好。我无法弄清楚如何访问用于表示集合中每个对象的视图上的各种控件。
以下是设置:
NSCollectionView
拖入我在IB中的视图。NSCollectionViewItem
的自定义子类。在IB中映射我的班级。NSBox
的自定义子类,作为集合中每个对象的视图。还在IB中映射了此类,并将其连接到我的view
子类的NSCollectionViewItem
属性。观点:
生成的集合视图:
推测我的NSCollectionViewItem
的子类基本上是集合中每个视图的控制器,我在控制器子类的视图中引用了各种控件的出口:
@interface SourceCollectionViewItem : NSCollectionViewItem
@property (weak) IBOutlet NSTextField *nameTextField;
@property (weak) IBOutlet NSTextField *typeTextField;
@property (weak) IBOutlet RSLabelView *labelView;
@property (weak) IBOutlet NSButton *viewButton;
@end
当我在调试器中检查SourceCollectionViewItem
的任何实例时,所有属性都显示为nil,尽管事实上我可以在屏幕上看到它们并且所有内容都显示为它应该是。
我的设置灵感来自Apple的示例应用IconCollection。
我显然缺少一些东西。什么?
编辑:我发现各种帖子暗示了类似的问题: 关于SO的CocoaBuilder.com和this question
编辑:只是为了完成:this post也处理主题,并根据接受的答案中提到的选项组合提供解决方案。
答案 0 :(得分:6)
在笔尖加载期间设置出口,并且仅从笔尖加载原型项并分配其出口。所有其他ViewItem
和它们的View
都是从原型中克隆出来的,在这种情况下,出口只是从未初始化的实例变量。
以下是我可以提出的选项:
newItemForRepresentedObject:
并重新加载nib,而不是克隆原型。但这可能会大大损害性能。copyWithZone
集合视图项并使用viewWithTag:
手动分配插座以查找它们。答案 1 :(得分:1)
我发现重写NSCollectionViewItem -setRepresentedObject:
也是一个不错的选择,因为当所有IBOutlet似乎准备就绪时,它会在新项目上调用。致电super
后,您可以做任何需要的事情:
- (void)setRepresentedObject:(id)representedObject
{
if (representedObject) {
[super setRepresentedObject:representedObject];
[self.anOutlet bind:@"property" toObject:self.representedObject withKeyPath:@"representeProperty" options:nil];
}
}
我使用此方法绑定接口对象的自定义属性。当representObject尚未准备好时,检查是为了避免无用的调用。该项目使用单独的xib作为ViewItem,如原始编辑中的链接所述。
答案 2 :(得分:0)
好问题。就像@hamstergene建议的那样,你可以使用copyWithZone
,与newItemForRepresentedObject
相比,它会更有效率。但是viewWithTag
并不总是一个选项,首先,因为不是所有东西都可以标记(轻松),其次,为此目的使用标记有点不对。在Swift中,这是一个考虑性能的很酷的方法。
import AppKit
class MyViewController: NSCollectionItemView
{
// Here you are cloning the original item loaded from the storyboard, which has
// outlets available, but as you've seen the default implementation doesn't take
// care of them. Each view has a unique identifiers, which you can use to find it
// in sublayers. What's really cool about this, is that you don't need to assign
// any tags or do anything else while having advantage of better performance using
// cached nib object.
override func copyWithZone(zone: NSZone) -> AnyObject {
let copy: NSCollectionItemView = super.copyWithZone(zone) as! NSCollectionItemView
let oldView: RecordingView = self.view as! MyView
let newView: RecordingView = copy.view as! MyView
newView.foo = newView.viewWithIdentifier(oldView.foo.identifier!) as! NSTextfield
newView.bar = newView.viewWithIdentifier(oldView.bar.identifier!) as! NSImageView
return copy
}
}
@IBDesignable class MyView: View
{
// Custom collection view item view. Lets assume inside of it you have two subviews which you want
// to access in your code.
@IBOutlet weak var foo: NSTextfield!
@IBOutlet weak var bar: NSImageView!
}
extension NSView
{
// Similar to viewWithTag, finds views with the given identifier.
func viewWithIdentifier(identifier: String) -> NSView? {
for subview in self.subviews {
if subview.identifier == identifier {
return subview
} else if subview.subviews.count > 0, let subview: NSView = subview.viewWithIdentifier(identifier) {
return subview
}
}
return nil
}
}