本文介绍了NSCollectionView sizeForItemAt在尝试引用其集合中的项目时始终返回异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文-

我正在使用macOS菜单栏应用程序,该应用程序显示项目的集合。这些项目存在于集合视图中并包含一个文本字段。

I am working on a macOS menu bar app which displays a collection of items. The items exist in a collection view and contain a textfield.

现在,集合视图的布局固定高度为50,我正在尝试动态增加

Right now, the collection view layout is at a fixed height of 50, and I am trying to dynamically increase the size of the cell based on the size of the textfield.

我相信做到这一点的最佳方法是在 sizeForItemAt 方法,但是我似乎无法引用一个单元格及其文本字段来计算并返回其高度。每当我此时尝试获取collectiomView项时,应用程序都会崩溃,并显示 [General] ***-[__ NSArrayM objectAtIndex:]:索引1超出范围[0 .. 0] 例外。

I believe the best way to do this is in the sizeForItemAt method, but I can not seem to reference a cell and its textfield to calculate and return it's height. Whenever I try and get a collectiomView item at this point, the app crashes with an [General] *** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0] exception.

我的代码-

我的viewDidLoad,在其中配置我的CollectionView

My viewDidLoad, where I 'configure' my CollectionView

override func viewDidLoad() {
    super.viewDidLoad()

    configureCollectionView()
    ....
}

private func configureCollectionView() {
    let flowLayout = NSCollectionViewFlowLayout()

    flowLayout.itemSize.width = self.view.frame.width
    flowLayout.minimumLineSpacing = 8
    thoughtsCollectionView.collectionViewLayout = flowLayout
    view.wantsLayer = true
}

这是我要动态设置高度(以及崩溃的位置)的地方

This is where Im trying to set the height dynamically (and where it crashes)

func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {

    guard collectionView.item(at: indexPath) != nil else { // <-- CRASHES HERE
        return NSSize(width: self.view.frame.width, height: 50)
    }

    return self.collectionView.item(at: indexPath)?.textField?.frame.height
}

这是我将项目添加到集合中的方式

This is how Im adding items to the collectionView

func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {

    let item = collectionView.makeItem(withIdentifier: "CollectionViewItem", for: indexPath as IndexPath)
    guard let collectionViewItem = item as? CollectionViewItem else {return item}

    (item as! CollectionViewItem).textField?.stringValue = "Some Text"

    (item as! CollectionViewItem).delegate = self

    return item
}

对我来说,奇怪的是在我的 collectionView(_ collectionView:NSCollectionView,didSelectItemsAt indexPaths:Set< IndexPath>)中,我是通过以下方式成功获取项目的

So what is strange to me, is that in my collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) I am to successfully get the item by doing

func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {

    guard let indexPath = indexPaths.first else {
        return
    }

    guard collectionView.item(at: indexPath) != nil else {
        return
    }

    let item = collectionView.item(at: indexPath) as! CollectionViewItem // <--- This gets me an item fine

所以我不确定为什么我在 sizeForItemAt 中挣扎。我有一种感觉,因为这些项目尚不存在(当视图开始显示它们时会创建它们),但是不确定如何正确地进行这种动态调整。

So I'm unsure why I'm struggling with sizeForItemAt. I have a feeling its because the items don't exist yet (and are created when the view starts to display them), but unsure how to then correctly approach this dynamic sizing.

推荐答案

我遇到了同样的问题。通过阅读文档,我发现Apple打算让我们使用 NSCollectionViewLayout 代替项目。

I encounter the same issue. With reading the documents, I find that Apple intents to let us use the NSCollectionViewLayout instead of the item.

如果您不知道如何处理 NSCollectionViewLayout ,则可以尝试使用数据模型来重新生成视图并进行计算。

If you don't know how to deal with NSCollectionViewLayout, you can try to use your data model to regenerate the views and calculate.

例如,如果您有一张图像,一个可变尺寸标签和一个固定尺寸标签。喜欢:图片|可变标签|标签

For example, if you have one image, one mutable size label and one fixed size label. like: Image | Mutable Label | Label

您可以像这样重新生成可变标签。

You can regenerate the mutable label like this.

func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {

    let imageViewWidth:CGFloat = 20 + 64 + 20
    let account = self.dataObject[indexPath]
    let defaultLabelWidth:CGFloat = {
        if account.isDefault {
            let defaultLabel = NSTextField(labelWithString: NSLocalizedString("Default", comment: ""))
            defaultLabel.font = NSFont.systemFont(ofSize: 16.0)
            defaultLabel.sizeToFit()

            return 20 + defaultLabel.bounds.width + 20
        }

        return 0 + 0 + 20
    }()

    let nameLabelWidth:CGFloat = {
        let label = NSTextField(labelWithString: account.name)
        label.font = NSFont.systemFont(ofSize: 16.0)
        label.sizeToFit()

        return label.bounds.width
    }()

    return NSSize(width: imageViewWidth + nameLabelWidth + defaultLabelWidth, height: 80)
}

这篇关于NSCollectionView sizeForItemAt在尝试引用其集合中的项目时始终返回异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 06:08