NSCollectionViewItem 子类中的自定义插座

发布于 2024-11-27 06:27:01 字数 1170 浏览 4 评论 0原文

我觉得这是一个简单的任务,但我似乎无法使其发挥作用。 我正在尝试使用带有自定义项目的 NSCollectionView 。我将另一个 NSImageView 添加到该项目的自定义视图中,并对该视图进行子类化,以便添加连接到此附加 NSImageView 的自定义插座。

现在我重写 - (NSCollectionViewItem *)newItemForRepresentedObject:(id)object 因为有时我需要删除这个 NSImageView。

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object {

    CustomItem *theItem = (CustomItem *)[super newItemForRepresentedObject: object];

    ...

    if (I need to remove that NSImageView) {

        [[theItem additionalImageView] removeFromSuperview];

    }

    return theItem;

}

无论如何,additionalImageView 似乎是(nil)。这在某种程度上是显而易见的,因为 super 方法将返回默认的 NSCollectionViewItem,它没有自定义插座。

在这里最好做什么?我读到了一些关于复制方法的内容,并尝试了:

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object {

    CustomItem *theItem = [(CustomItem *)[super itemPrototype] copy]; // Here is the change

    ...

    if (I need to remove that NSImageView) {

        [[theItem additionalImageView] removeFromSuperview];

    }

    return theItem;

}

但这是行不通的。那么,有没有办法在使用自定义 NSCollectionViewItem 时保留自定义插座?

任何帮助将不胜感激。谢谢你!

I feel this being a simple task, but I don't seem to be able to make it work.
I'm trying to have a NSCollectionView with custom items. I added another NSImageView to the custom view of the item, and I subclassed this view in order to add the custom outlet connected to this additional NSImageView.

Now I am overriding - (NSCollectionViewItem *)newItemForRepresentedObject:(id)object because sometimes I need to remove this NSImageView.

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object {

    CustomItem *theItem = (CustomItem *)[super newItemForRepresentedObject: object];

    ...

    if (I need to remove that NSImageView) {

        [[theItem additionalImageView] removeFromSuperview];

    }

    return theItem;

}

Anyway, additionalImageView seems to be (nil). This is someway obvious because the super method will return the default NSCollectionViewItem which has not the custom outlet.

What's the best thing to do right here? I read something about the copy method, and I tried with:

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object {

    CustomItem *theItem = [(CustomItem *)[super itemPrototype] copy]; // Here is the change

    ...

    if (I need to remove that NSImageView) {

        [[theItem additionalImageView] removeFromSuperview];

    }

    return theItem;

}

But this is not going to work. So, is there a way to preserve custom outlets when using a custom NSCollectionViewItem?

Any help would be very appreciated. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天荒地未老 2024-12-04 06:27:01

问题是没有人会实例化新项目的图像视图。复制不起作用,因为您需要两个图像视图,而不是一个。

有两种方法可以处理此问题:

  1. 不要调用 newItemForRepresentedObject 的超类实现,而是使用 NSNIb 自己实例化该项目(下面的工厂方法)。在方法调用中,您可以指定 self 作为所有者,它将为您连接插座。然后设置representedObject并调整图像视图。这是工厂方法的代码:

    // 从 CustomItem.nib 加载项目视图
    // 为了获得一致的结果,nib 应恰好包含一个 NSCollectionViewItem。
    - (NSCollectionViewItem *)newCollectionViewItem {
        静态 NSNib *nib;
        if (!nib) nib = [[NSNib alloc] initWithNibNamed:@"CustomItem" bundle:nil];
    
        NSArray *nibObjects;
        if (![nib instantiateNibWithOwner:self topLevelObjects:&nibObjects]) return nil;
    
        for (nibObjects 中的 id obj)
            if ([obj isKindOfClass:[NSCollectionViewItem 类]])
                返回 (NSCollectionViewItem *)obj;
    
        返回零;
    }
    
  2. 调用[super newItemForRepresentedObject:]后,检查是否需要保留图像视图。如果这样做,请实例化一个新的 NSImageView,设置其属性,并将其添加到超级视图。最后一部分听起来很棘手。也许采用这种方法的人会提供一些代码。

The problem is that no one will instantiate the new item's image view. Copy won't work, since you need two image views, not one.

There are two ways to handle this:

  1. Instead of calling the superclass implementation of newItemForRepresentedObject, use NSNib to instantiate the item yourself (factory method below). In the method call, you can specify self as the owner, and it will hook up the outlets for you. Then set representedObject and fiddle with the image view. Here's code for the factory method:

    // Load item view from CustomItem.nib
    // For consistent results, nib should contain exactly one NSCollectionViewItem.
    - (NSCollectionViewItem *)newCollectionViewItem {
        static NSNib *nib;
        if (!nib) nib = [[NSNib alloc] initWithNibNamed:@"CustomItem" bundle:nil];
    
        NSArray *nibObjects;
        if (![nib instantiateNibWithOwner:self topLevelObjects:&nibObjects]) return nil;
    
        for (id obj in nibObjects)
            if ([obj isKindOfClass:[NSCollectionViewItem class]])
                return (NSCollectionViewItem *)obj;
    
        return nil;
    }
    
  2. After you call [super newItemForRepresentedObject:], check if you need to keep the image view. If you do, instantiate a new NSImageView, set its properties, and add it to the superview. That last part sounds tricky. Maybe someone who's taken that approach will provide some code.

度的依靠╰つ 2024-12-04 06:27:01

解决该问题的一种方法是创建 2 个不同的原型视图并将它们绑定到您的控制器。现在,当您位于 newItemForRepresentedObject 中时,您可以使用副本设置 NSCollectionViewItemview(使用 NSCoding协议)的适当原型取决于对象。我使用从 super 获得的 NSCollectionViewItem

这里是我的示例代码,用于显示未知 NSManagedObject 的字符串或数字属性编辑器,NSManagedAttribute 是一个实用程序类,我将其用作集合视图的表示对象并保留有关属性/关系的信息

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object{
    NSManagedAttribute *attribute = object;
    NSCollectionViewItem *item =[super newItemForRepresentedObject:object];
    NSData * archivedView = nil;
    if (attribute.attributeType == NSInteger16AttributeType){
        archivedView = [NSKeyedArchiver archivedDataWithRootObject:self.controller.integerView];
    } else if (attribute.attributeType == NSStringAttributeType) {
        archivedView = [NSKeyedArchiver archivedDataWithRootObject:self.controller.stringView];
    }
    NSView * viewCopy = [NSKeyedUnarchiver unarchiveObjectWithData:archivedView];
    item.view = viewCopy;
    return item;
}

它对我有用:-)

One way to solve the problem is to create 2 different prototype views and bind them to your controller. Now when you are in the newItemForRepresentedObject you can set the view of your NSCollectionViewItem with a copy (using the NSCoding protocol) of the appropriate prototype depending on the object. I use the NSCollectionViewItem I get from super.

Here My sample code for the casa of showing a string or a number attribute editor of an unknown NSManagedObject, NSManagedAttribute is a utility class that I use as represented object for my collection view and keeps information about the attribute/relationship

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object{
    NSManagedAttribute *attribute = object;
    NSCollectionViewItem *item =[super newItemForRepresentedObject:object];
    NSData * archivedView = nil;
    if (attribute.attributeType == NSInteger16AttributeType){
        archivedView = [NSKeyedArchiver archivedDataWithRootObject:self.controller.integerView];
    } else if (attribute.attributeType == NSStringAttributeType) {
        archivedView = [NSKeyedArchiver archivedDataWithRootObject:self.controller.stringView];
    }
    NSView * viewCopy = [NSKeyedUnarchiver unarchiveObjectWithData:archivedView];
    item.view = viewCopy;
    return item;
}

It is working for me :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文