Swift迁移代码报错:Dictionary.Values无法用+合并的解决咨询
Hey there! Let's tackle that error you're hitting when merging dictionary values. The root issue is simple: Dictionary.Values is a specialized collection type, not an array, so Swift doesn't let you use the + operator directly on it.
The Problem with Your Current Code
In these lines, you're trying to add Dictionary.Values instances together, which isn't allowed:
var result = cellAttrDict.values + supplHeaderAttrDict.values result = result + supplFooterAttrDict.values result = result + decorAttrDict.values
The Solution: Convert to Arrays First
All you need to do is convert each Dictionary.Values collection to an array using Array(), then you can use the + operator (or += for appending) as expected. Here's how to update those lines:
// Convert each dictionary's values to arrays before merging var result = Array(cellAttrDict.values) + Array(supplHeaderAttrDict.values) result += Array(supplFooterAttrDict.values) result += Array(decorAttrDict.values)
Or for a more concise, readable approach:
let result = Array(cellAttrDict.values) + Array(supplHeaderAttrDict.values) + Array(supplFooterAttrDict.values) + Array(decorAttrDict.values)
Bonus: Clean Up Optional Handling (Optional)
While we're at it, you can make your code safer by replacing forced unwraps (as!) with optional binding to avoid runtime crashes. For example, instead of:
if rect.intersects(unionRects[i] as! CGRect) {
You can write:
guard let unionRect = unionRects[i] as? CGRect else { continue } if rect.intersects(unionRect) {
This makes your code more robust if unionRects ever contains non-CGRect values.
Full Updated Method
Here's your complete method with the fix applied, plus some type-safety improvements:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var begin = 0 var end = unionRects.count var cellAttrDict: [AnyHashable : UICollectionViewLayoutAttributes] = [:] var supplHeaderAttrDict: [AnyHashable : UICollectionViewLayoutAttributes] = [:] var supplFooterAttrDict: [AnyHashable : UICollectionViewLayoutAttributes] = [:] var decorAttrDict: [AnyHashable : UICollectionViewLayoutAttributes] = [:] for i in 0..<unionRects.count { guard let unionRect = unionRects[i] as? CGRect else { continue } if rect.intersects(unionRect) { begin = i * unionSize break } } var i = unionRects.count - 1 while i >= 0 { guard let unionRect = unionRects[i] as? CGRect else { i -= 1 continue } if rect.intersects(unionRect) { end = min((i + 1) * unionSize, allItemAttributes.count) break } i -= 1 } for i in begin..<end { guard let attr = allItemAttributes[i] as? UICollectionViewLayoutAttributes else { continue } guard rect.intersects(attr.frame) else { continue } switch attr.representedElementCategory { case .supplementaryView: if attr.representedElementKind == CHTCollectionElementKindSectionHeader { supplHeaderAttrDict[attr.indexPath] = attr } else if attr.representedElementKind == CHTCollectionElementKindSectionFooter { supplFooterAttrDict[attr.indexPath] = attr } case .decorationView: decorAttrDict[attr.indexPath] = attr case .cell: cellAttrDict[attr.indexPath] = attr @unknown default: break } } // Fixed value merging by converting to arrays let result = Array(cellAttrDict.values) + Array(supplHeaderAttrDict.values) + Array(supplFooterAttrDict.values) + Array(decorAttrDict.values) return result }
I also updated the dictionary types to explicitly use UICollectionViewLayoutAttributes instead of Any—this makes your code more type-safe and removes the need for the final as? cast when returning.
内容的提问来源于stack exchange,提问作者uma

