You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:48:47