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

SwiftUI ForEach循环嵌套If语句优化及Xcode报错问题咨询

解决方案

核心优化思路

你遇到的Xcode报错是因为SwiftUI的ViewBuilder需要同时推导多个条件分支的视图类型,视图结构越复杂编译期类型计算开销越大,超过阈值就会抛出该错误。优化方向分为两步:抽离重复的子视图、把零散的verse属性转换为可遍历的数组,完全消除重复的if判断。

步骤1:抽离通用的节视图

把重复的verse行视图抽成独立的VerseRow子视图,减少重复代码:

struct VerseRow: View {
    /// 节数
    let number: Int
    /// 歌词内容
    let content: String
    /// 是否显示节数图标
    let showNumber: Bool
    /// 字体名称
    let fontName: String
    /// 字体大小
    let fontSize: CGFloat
    
    var body: some View {
        HStack {
            if showNumber {
                Image(systemName: "\(number).circle.fill")
                    .font(.title2)
                    .foregroundColor(.red)
            }
            Text(content)
                .font(.custom(fontName, size: fontSize))
            Spacer()
        }
    }
}

步骤2:给Lyric扩展可遍历的节数组

给Lyric模型添加扩展,把零散的verse2~verse5属性整合为带序号的数组,不需要手动逐个判空:

extension Lyric {
    /// 整理好的带序号非空节列表
    var validVerses: [(number: Int, content: String)] {
        var list = [(Int, String)]()
        if let verse2 = verse2 { list.append((2, verse2)) }
        if let verse3 = verse3 { list.append((3, verse3)) }
        if let verse4 = verse4 { list.append((4, verse4)) }
        if let verse5 = verse5 { list.append((5, verse5)) }
        return list
    }
}

步骤3:改造原Home视图的循环逻辑

替换原来的4个重复if判断,用ForEach遍历整理好的节数组即可:

import SwiftUI

struct Home: View {
    
    var lyrics: [Lyric] = LyricList.hymnLa
    @AppStorage("fontSizeIndex") var fontSizeIndex = 18 // 原写法Int("Medium")永远返回nil,建议根据实际需求调整存储逻辑
    @AppStorage("fontIndex") var fontIndex: String = ""
    @AppStorage("showHVNumbers") var showHVNumbers: Bool = true
    // 注意:原代码用到的scrollToIndex未定义,需自行补全属性声明
    
    var body: some View {
        ScrollView {
            ScrollViewReader { proxy in
                LazyVStack(spacing: 10) {
                    ForEach (lyrics, id: \.id) { lyric in
                        // 直接遍历非空节数组,无重复代码
                        ForEach(lyric.validVerses, id: \.number) { verse in
                            VerseRow(
                                number: verse.number,
                                content: verse.content,
                                showNumber: showHVNumbers,
                                fontName: fontIndex,
                                fontSize: CGFloat(fontSizeIndex)
                            )
                        }
                    }
                    .foregroundColor(.primary)
                    .padding(.horizontal, 10.0)
                    .padding(.bottom)
                    
                    Divider()
                }
                .onChange(of: scrollToIndex, perform: { value in
                    proxy.scrollTo(value, anchor: .top)
                })
            }
        }
    }
}

额外说明

修改后编译期不需要再推导多个独立的if分支视图类型,复杂度大幅降低,即可解决Expression was too complex to be solved in reasonable time报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 18:36:03