ios - 将项目从目标 c 移动到 swift 时,“AnyHashable”类型的值没有下标
问题描述
我实际上正在将我的目标 c 项目迁移到 swift,我对 swift 也不太熟悉。我在所有columnHeights
. 基本上,此类是设计以 pintrest 格式显示的 ui 的课程之一。此行出错-> columnHeights[section][idx] = NSNumber(value: Float(top))
Xcode = 10.3
快速 = 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
直接使用
推荐阅读
- c++ - 在函数中而不是在文件开头初始化静态变量
- excel - 如何在 Excel 中设置动态范围
- javascript - 角度 ngif 不随变量而变化
- javascript - 打字稿根据给定值返回键数组
- java - 带有 JUnit 5 的 WELD SE 需要以编程方式启用 bean 发现
- node.js - 如何使用现代 nodeJS 动态选择模块?
- javascript - 在 connect() 函数运行后,如何从应用程序级别状态传递 componentWillMount 中的道具?
- reactjs - 如何在 React 中渲染来自 props 的数据
- macos - 滚动 NSTableView 到 endOfDocument 而不是最后一行
- java - 如何在 Web 托管服务器上托管 Spring Boot 应用程序