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

SwiftUI中如何初始将枚举allCases值填充至空sportsArray数组

解决SwiftUI中默认全选运动项的问题

问题说明

已实现按钮点击切换选中状态,可将运动项添加/移除至sportsArray数组,但无法实现当sportsArray初始为空时,自动把枚举HelperIntervalsIcu.icuActivityType.allCases的所有值初始化到数组中。直接在视图代码里添加初始化逻辑时,Xcode持续报错type() cannot conform to View。

尝试的错误代码

if sportsArray.isEmpty {
  HelperIntervalsIcu.icuActivityType.allCases.forEach {
    sportsArray.append($0.rawvalue) // 注意此处rawvalue拼写错误,应为rawValue
  } 
}

相关完整代码

struct selectSports: View {
  @State private var sportsArray = [String]()
   
  var body: some View {

    ScrollView(.horizontal, showsIndicators: false) {
      HStack {
        ForEach(Array(HelperIntervalsIcu.icuActivityType.allCases), id:\.rawValue) { sport in
          Button(action: {
            addSports(sport: sport.rawValue)
          }) {
            HStack {
              Image(getSportsIcon(sport: sport.rawValue))
                .selectedSportsImageStyle(sportsArray: sportsArray, sport: sport.rawValue)
              Text(sport.rawValue)
            }
          }
          .buttonStyle(SelectedSportButtonStyle(sportsArray: sportsArray, sport: sport.rawValue))
        }
      }
    }
  }
  
  struct SelectedSportButtonStyle: ButtonStyle {
    var sportsArray: [String]
    var sport: String
    
    var selectedSport : Bool {
      sportsArray.contains(sport)
    }

    func makeBody(configuration: Self.Configuration) -> some View {
      configuration.label
        .font(selectedSport ? Font.subheadline.bold() : Font.subheadline)
        .aspectRatio(contentMode: .fit)
        .foregroundColor(selectedSport ? Color.orange : Color(UIColor.label))
        .padding([.leading, .trailing], 15)
        .padding([.top, .bottom],10)
        .overlay(
          RoundedRectangle(cornerRadius: 5.0)
            .stroke(lineWidth: 2.0)
            .foregroundColor(selectedSport ? Color.orange : Color.gray)
        )
        .offset(x: 10, y: 0)
    }
  }
  
  func addSports(sport: String) {
    if let index = sportsArray.firstIndex(of: sport) {
      sportsArray.remove(at: index)
    } else {
      sportsArray.append(sport)
    }
    print("Selected Sports:\(sportsArray)")
  }
}

需求

将当前“初始空数组无选中项”的逻辑,改为默认全选所有运动项。

解决方案

方案1:直接初始化@State变量(推荐)

SwiftUI的@State变量可以在声明时直接赋值,不需要在视图的body中处理。修改sportsArray的初始化代码,直接将所有枚举的rawValue填充进去:

@State private var sportsArray = HelperIntervalsIcu.icuActivityType.allCases.map { $0.rawValue }

这样视图加载时,数组就已经包含所有运动项,默认全选。

方案2:利用视图生命周期方法初始化

如果需要保留“数组为空时才初始化”的逻辑,或者不想在声明时直接赋值,可以使用.onAppear修饰符,在视图首次出现时执行初始化:

ScrollView(.horizontal, showsIndicators: false) {
  // 原有HStack及按钮代码
}
.onAppear {
  if sportsArray.isEmpty {
    // 修正rawValue的拼写错误
    sportsArray = HelperIntervalsIcu.icuActivityType.allCases.map { $0.rawValue }
  }
}

错误原因解释

之前的代码报错是因为SwiftUI的body是ViewBuilder,只能返回View类型的内容,不能直接在body中编写修改状态的逻辑代码(比如修改sportsArray的操作),这类副作用代码应该放在视图生命周期方法(如.onAppear)或者初始化代码中。

另外,你尝试的代码里还有一个拼写错误:$0.rawvalue应该改为$0.rawValue(大写V),这也是潜在的问题点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 13:54:22