iOS开发:子视图删除与替换的处理方法及SET游戏Grid布局场景
嘿,我来帮你搞定这个问题!结合你手里的Grid.swift工具,咱们可以轻松搞定SET游戏里卡片视图的删除和替换,完全适配你首批展示12张卡的需求:
一、先搞定初始12张卡片的布局(基础铺垫)
首先咱们用Grid的dimensions布局(固定3行4列,刚好放下12张卡),把卡片视图和Grid的索引绑定,方便后续操作。建议维护一个数组来存所有卡片视图,比单纯用tag更可靠:
// 假设你有一个用来装卡片的父视图cardContainer var grid = Grid(layout: .dimensions(rowCount: 3, columnCount: 4), frame: cardContainer.bounds) var cardViews = [UIView]() // 存所有卡片视图,方便后续删除/替换 // 初始化12张卡片 for index in 0..<12 { guard let cellFrame = grid[index] else { continue } let cardView = CardView() // 这里替换成你的自定义卡片视图类 cardView.frame = cellFrame cardContainer.addSubview(cardView) cardViews.append(cardView) }
二、处理卡片视图的删除
删除分两种场景:单张删除、批量删除(比如移除选中的SET组合)
1. 单张卡片删除
直接从数组里取出对应卡片,移除后同步更新数组:
func removeCard(at index: Int) { guard index < cardViews.count else { return } let cardToRemove = cardViews[index] cardToRemove.removeFromSuperview() cardViews.remove(at: index) }
2. 批量删除(比如移除3张SET卡片)
注意要倒序删除,避免因为数组元素移位导致索引混乱:
func removeCards(at indices: [Int]) { // 先把索引倒序排列 let sortedIndices = indices.sorted(by: >) for index in sortedIndices { guard index < cardViews.count else { continue } let card = cardViews[index] card.removeFromSuperview() cardViews.remove(at: index) } }
三、处理卡片视图的替换
替换也分单张替换和批量替换(比如删除SET组合后补3张新卡)
1. 单张卡片替换
先移除旧卡片,再用Grid获取对应位置的frame,添加新卡片并更新数组:
func replaceCard(at index: Int, with newCard: UIView) { guard index < cardViews.count, let cellFrame = grid[index] else { return } // 移除旧卡片 let oldCard = cardViews[index] oldCard.removeFromSuperview() // 设置新卡片位置并添加 newCard.frame = cellFrame cardContainer.addSubview(newCard) // 更新数组 cardViews[index] = newCard }
2. 批量替换(补新卡片)
如果删除3张后需要补新卡,直接遍历Grid的所有位置,把空出来的位置补上:
func addNewCards(_ newCards: [UIView]) { var newCardIndex = 0 // 遍历Grid的12个位置,找空的位置补卡 for gridIndex in 0..<grid.cellCount { guard newCardIndex < newCards.count else { break } // 检查这个位置是否已有卡片 let hasCard = cardViews.contains { $0.frame == grid[gridIndex] } if !hasCard { let newCard = newCards[newCardIndex] newCard.frame = grid[gridIndex] ?? newCard.frame cardContainer.addSubview(newCard) cardViews.append(newCard) newCardIndex += 1 } } }
四、关键注意事项
- 适配屏幕旋转:当父视图frame变化时,要同步更新Grid的frame,然后重新调整所有卡片的位置:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() grid.frame = cardContainer.bounds // 更新所有卡片的位置 for (index, cardView) in cardViews.enumerated() { cardView.frame = grid[index] ?? cardView.frame } }
- 避免视图叠加:删除/替换时一定要调用
removeFromSuperview(),不然旧视图会留在父视图里,和新视图叠加。 - 数据视图同步:始终维护
cardViews数组,确保数组里的元素和父视图中的卡片视图一一对应,这比用tag查找更不容易出错。
内容的提问来源于stack exchange,提问作者INFORMATIKER IM ALL
相关产品推荐
相关产品推荐

