ios - 将项目从 Objective C 移动到 Swift 时,类型 'AnyHashable' 的值没有下标

标签 ios swift migration

我实际上正在将我的 Objective C 项目迁移到 Swift,但我对 Swift 也不太熟悉。我在所有 columnHeights 中收到“‘AnyHashable’类型的值没有下标” 错误。基本上这个类是设计以 pintrest 格式显示的 ui 的类之一。此行出错 -> columnHeights[section][idx] = NSNumber(value: Float(top))

Xcode = 10.3
swift = 5

// MARK: - Methods to Override
override func prepare() {
    super.prepare()

    headersAttribute.removeAll()
    footersAttribute.removeAll()
    unionRects.removeAll()
    columnHeights.removeAll()
    allItemAttributes.removeAll()
    sectionItemAttributes.removeAll()

    let numberOfSections = collectionView?.numberOfSections
    if numberOfSections == 0 {
        return
    }

    assert(delegate is CHTCollectionViewDelegateWaterfallLayout ?? false, "UICollectionView's delegate should conform to CHTCollectionViewDelegateWaterfallLayout protocol")
    assert(self.columnCount > 0 || delegate?.responds(to: #selector(CHTCollectionViewDelegateWaterfallLayout.collectionView(_:layout:columnCountForSection:))) ?? false, "UICollectionViewWaterfallLayout's columnCount should be greater than 0, or delegate must implement columnCountForSection:")

    // Initialize variables
    var idx = 0

    for section in 0..<(numberOfSections ?? 0) {
        let columnCount = self.columnCount(forSection: section)
        var sectionColumnHeights = [AnyHashable](repeating: 0, count: columnCount)
        for idx in 0..<columnCount {
            sectionColumnHeights.append(NSNumber(value: 0))
        }
        columnHeights.append(sectionColumnHeights)
    }
    // Create attributes
    var top: CGFloat = 0
    var attributes: UICollectionViewLayoutAttributes?

    for section in 0..<(numberOfSections ?? 0) {
        /*
         * 1. Get section-specific metrics (minimumInteritemSpacing, sectionInset)
         */
        var minimumInteritemSpacing: CGFloat
        if delegate?.responds(to: #selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:minimumInteritemSpacingForSectionAt:))) ?? false {
            if let collectionView = collectionView {
                minimumInteritemSpacing = delegate?.collectionView?(collectionView, layout: self, minimumInteritemSpacingForSectionAt: section) ?? 0.0
            }
        } else {
            minimumInteritemSpacing = self.minimumInteritemSpacing
        }

        var columnSpacing = minimumColumnSpacing
        if delegate?.responds(to: #selector(CHTCollectionViewDelegateWaterfallLayout.collectionView(_:layout:minimumColumnSpacingForSectionAt:))) ?? false {
            columnSpacing = delegate?.collectionView?(collectionView, layout: self, minimumColumnSpacingForSectionAt: section) ?? 0.0
        }

        var sectionInset: UIEdgeInsets
        if delegate?.responds(to: #selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:insetForSectionAt:))) ?? false {
            if let collectionView = collectionView, let collection = delegate?.collectionView?(collectionView, layout: self, insetForSectionAt: section) {
                sectionInset = collection
            }
        } else {
            sectionInset = self.sectionInset
        }

        let width = (collectionView?.bounds.size.width ?? 0.0) - sectionInset.left - sectionInset.right
        let columnCount = self.columnCount(forSection: section)
        let itemWidth = CHTFloorCGFloat((width - CGFloat((columnCount - 1)) * columnSpacing) / CGFloat(columnCount))

        /*
         * 2. Section header
         */
        var headerHeight: CGFloat
        if delegate?.responds(to: #selector(CHTCollectionViewDelegateWaterfallLayout.collectionView(_:layout:heightForHeaderInSection:))) ?? false {
            headerHeight = delegate?.collectionView?(collectionView, layout: self, heightForHeaderInSection: section) ?? 0.0
        } else {
            headerHeight = self.headerHeight
        }

        var headerInset: UIEdgeInsets
        if delegate?.responds(to: #selector(CHTCollectionViewDelegateWaterfallLayout.collectionView(_:layout:insetForHeaderInSection:))) ?? false {
            if let collection = delegate?.collectionView?(collectionView, layout: self, insetForHeaderInSection: section) {
                headerInset = collection
            }
        } else {
            headerInset = self.headerInset
        }

        top += headerInset.top

        if headerHeight > 0 {
            attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: CHTCollectionElementKindSectionHeader, with: IndexPath(item: 0, section: section))
            attributes?.frame = CGRect(x: headerInset.left, y: top, width: (collectionView?.bounds.size.width ?? 0.0) - (headerInset.left + headerInset.right), height: headerHeight)

            if let attributes = attributes {
                headersAttribute[NSNumber(value: section)] = attributes
            }
            if let attributes = attributes {
                allItemAttributes.append(attributes)
            }

            top = attributes?.frame.maxY ?? 100 + headerInset.bottom
        }

        top += sectionInset.top
        for idx in 0..<columnCount {
           columnHeights[section][idx] = NSNumber(value: Float(top))

        }

        /*
         * 3. Section items
         */
        let itemCount = collectionView?.numberOfItems(inSection: section)
        var itemAttributes = [AnyHashable](repeating: 0, count: itemCount ?? 0)

        // Item will be put into shortest column.
        for idx in 0..<(itemCount ?? 0) {
            let indexPath = IndexPath(item: idx, section: section)
            let columnIndex = nextColumnIndex(forItem: idx, inSection: section)
            let xOffset = sectionInset.left + (itemWidth + columnSpacing) * CGFloat(columnIndex)
           swift let yOffset = CGFloat((columnHeights[section][columnIndex] as? NSNumber)?.floatValue)
            var itemSize: CGSize? = nil
            if let collectionView = collectionView {
                itemSize = delegate?.collectionView?(collectionView, layout: self, sizeForItemAt: indexPath)
            }
            var itemHeight: CGFloat = 0
            if (itemSize?.height ?? 0.0) > 0 && (itemSize?.width ?? 0.0) > 0 {
                itemHeight = CHTFloorCGFloat((itemSize?.height ?? 0.0) * itemWidth / (itemSize?.width ?? 0.0))
            }

            attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes?.frame = CGRect(x: xOffset, y: yOffset, width: itemWidth, height: itemHeight)
            if let attributes = attributes {
                itemAttributes.append(attributes)
            }
            if let attributes = attributes {
                allItemAttributes.append(attributes)
            }
            columnHeights[section][columnIndex] = NSNumber(value: Float(attributes?.frame.maxY + minimumInteritemSpacing))
        }

        sectionItemAttributes.append(itemAttributes)

        /*
         * 4. Section footer
         */
        var footerHeight: CGFloat
        let columnIndex = longestColumnIndex(inSection: section)
        if ((columnHeights[section] as? [Any])?.count ?? 0) > 0 {
            top = CGFloat((columnHeights[section][columnIndex] as? NSNumber)?.floatValue) - minimumInteritemSpacing + sectionInset.bottom
        } else {
            top = 0
        }

        if delegate?.responds(to: #selector(CHTCollectionViewDelegateWaterfallLayout.collectionView(_:layout:heightForFooterInSection:))) ?? false {
            footerHeight = delegate?.collectionView?(collectionView, layout: self, heightForFooterInSection: section) ?? 0.0
        } else {
            footerHeight = self.footerHeight
        }

        var footerInset: UIEdgeInsets
        if delegate?.responds(to: #selector(CHTCollectionViewDelegateWaterfallLayout.collectionView(_:layout:insetForFooterInSection:))) ?? false {
            if let collection = delegate?.collectionView?(collectionView, layout: self, insetForFooterInSection: section) {
                footerInset = collection
            }
        } else {
            footerInset = self.footerInset
        }

        top += footerInset.top

        if footerHeight > 0 {
            attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: CHTCollectionElementKindSectionFooter, with: IndexPath(item: 0, section: section))
            attributes?.frame = CGRect(x: footerInset.left, y: top, width: (collectionView?.bounds.size.width ?? 0.0) - (footerInset.left + footerInset.right), height: footerHeight)

            if let attributes = attributes {
                footersAttribute[NSNumber(value: section)] = attributes
            }
            if let attributes = attributes {
                allItemAttributes.append(attributes)
            }

            top = attributes?.frame.maxY + footerInset.bottom
        }

        for idx in 0..<columnCount {
            columnHeights[section][idx] = NSNumber(value: Float(top))
        }
        // end of for (NSInteger section = 0; section < numberOfSections; ++section)
    }

    // Build union rects
    idx = 0
    let itemCounts = allItemAttributes.count
    while idx < itemCounts {
        var unionRect = (allItemAttributes[idx] as? UICollectionViewLayoutAttributes)?.frame
        let rectEndIndex = min(idx + unionSize, itemCounts)

        for i in idx + 1..<rectEndIndex {
            unionRect = unionRect?.union((allItemAttributes[i] as? UICollectionViewLayoutAttributes)?.frame)
        }

        idx = rectEndIndex

        unionRects.append(NSValue(cgRect: unionRect ?? CGRect.zero))
    }
}

最佳答案

Swift 的好处之一是不强制在集合中使用对象(引用类型)。

顾名思义,columnHeights 似乎是 CGFloat 实例的嵌套数组。

声明一下

var columnHeights = [[CGFloat]]()

并填充它

let sectionColumnHeights = [CGFloat](repeating: 0.0, count: columnCount)
columnsHeights.append(sectionColumnHeights)

在所有其他出现的 columnHeights 中,删除 NSNumber 对象的创建并直接使用 CGFloat

关于ios - 将项目从 Objective C 移动到 Swift 时,类型 'AnyHashable' 的值没有下标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57819512/

相关文章:

ios - 当应用程序在后台时处理本地推送通知

swift - UIWindow endDisablingInterfaceAutorotationAnimated 错误仅在 iOS9 中从 collectionView 中以交互方式解除键盘时出现在控制台中

mysql - SQLSTATE[42000] : Syntax error or access violation: 1064 error on ALL Magento MySQL setup files after migration

ruby-on-rails - rails : is there a difference between 'references :foo' and 'integer :foo_id' ?

arrays - 你能在不知道swift类型的情况下声明一个空数组吗

migration - 如何将单个 DotNetNuke 门户移动到新服务器?

ios - GradientLayer 在 Swift 中的单元格标签上重叠?

ios - 已取消订阅 channel ,但仍在 channel 中

iphone - 在 iOS 上添加与 tiff 文件的文件关联

swift - SceneKit-Xcode 9 : removing the box's line border