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

MatchedGeometryEffect中isHidden失效:多视图插入错误排查

问题原因分析

  1. 视图与数据不同步:
    Board视图里的arr是初始化时赋值的常量,后续dm.wordArray更新时,arr不会自动同步,导致视图依然渲染旧数据,原选中瓷砖无法被正确移除。
  2. matchedGeometryEffect ID冲突:
    执行wordArray[row][col] = temp后,顶部瓷砖的对象同时存在于原顶部位置和选中位置,两个视图共用同一个word作为matchedGeometryEffect的ID,触发了"多个source视图匹配同一ID"的错误,最终出现瓷砖重叠。
  3. 隐藏逻辑失效:
    你先给原选中瓷砖设置isHidden = true,但随后用temp替换了该位置的对象,此时设置的隐藏状态只对被替换的旧对象生效,新赋值的temp对象isHidden为false,所以选中位置的新瓷砖不会隐藏,旧瓷砖因视图未同步还在渲染,导致重叠。

解决方案

1. 修复视图数据同步问题

直接在Board视图中使用dm.wordArray,去掉初始化时的常量arr,确保数据变化时视图实时刷新:

struct Board: View {
    @ObservedObject var dm: DataModel
    
    @Namespace var namespace
    
    var body: some View {
        ZStack{
            VStack(spacing: 10) {
                ForEach(0 ..< 4) { i in
                        HStack(spacing: 10) {
                            ForEach(0 ..< 4) { j in
                                Tile(word: dm.wordArray[i][j]!, dm: dm)
                                    .modifier(Shake(animatableData: CGFloat(dm.shakes[i][j] ? 1 : 0)))
                                    .opacity(dm.wordArray[i][j]!.isHidden ? 0 : 1)
                                    .matchedGeometryEffect(id: dm.wordArray[i][j]!.word, in: namespace)
                            }
                        }
                }
            }
        }
    }
}

2. 调整数据更新逻辑,避免ID冲突

同时处理顶部位置的瓷砖状态,确保同一个ID只对应一个视图:

if row != topmostRow {
    let temp = wordArray[topmostRow][leftmostCol]
    let oldSelectedTile = wordArray[row][col]
    
    withAnimation(.linear(duration: 0.4)) {
        // 隐藏原选中瓷砖
        oldSelectedTile?.isHidden = true
        // 隐藏顶部原位置的瓷砖(或替换为新瓷砖,根据业务需求)
        wordArray[topmostRow][leftmostCol]?.isHidden = true
        // 将顶部瓷砖移动到选中位置
        wordArray[row][col] = temp
    }
}

如果顶部位置需要生成新瓷砖,直接替换wordArray[topmostRow][leftmostCol]为新的Word对象,彻底避免同一ID重复出现。

3. 确保matchedGeometryEffect ID唯一

给Word模型添加唯一UUID标识,替代word字符串作为ID,从根源避免重复:

// 修改Word模型
struct Word: Identifiable {
    let id = UUID()
    var word: String
    var isHidden: Bool = false
    // 其他属性
}

// 在Board视图中使用唯一ID
.matchedGeometryEffect(id: dm.wordArray[i][j]!.id, in: namespace)

内容的提问来源于stack exchange,提问作者hstutea

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:28:35