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

如何为自定义DisclosureGroup添加接收字符串的初始化方法?

问题:自定义DisclosureGroup字符串标签初始化方法无法正常运行

自定义的CustomDisclosureGroup结构体包含两个初始化方法,第一个接收自定义LabelContent的方法可正常工作,但第二个接收字符串的初始化方法存在问题——Xcode要求添加强制类型转换as! LabelContent,且取消注释调用代码后无法正常运行。需要实现一个仅接收字符串作为标签的正确初始化方法。

原代码如下:

public struct CustomDisclosureGroup<LabelContent: View, Content: View>: View {
  var label: LabelContent
  var content: Content
  @Binding var isExpanded: Bool
  
  public init(isExpanded: Binding<Bool>, @ViewBuilder label: () -> LabelContent, @ViewBuilder content: () -> Content) {
    self.label = label()
    self.content = content()
    self._isExpanded = isExpanded
  }
  
  public init(labelString: String, isExpanded: Binding<Bool>, @ViewBuilder content: () -> Content) {
    self.init(isExpanded: isExpanded, label: { Text(labelString) as! LabelContent }, content: content)
  }
  
  public var body: some View {
    DisclosureGroup(isExpanded: $isExpanded) {
      content
    } label: {
      label
    }
  }
}

@main
struct TestDisclosureApp: App {
  @StateObject var topModel = TopModel()
  
  var body: some Scene {
    WindowGroup {
      ContentView()
    }
  }
}

struct ContentView: View {
  @EnvironmentObject var topModel: TopModel
  @State var isExpanded1 = false
  @State var isExpanded2 = false

  var body: some View {

    CustomDisclosureGroup(isExpanded: $isExpanded1, label: { Text("Label") }) {
      HStack {
        Text("Content1")
      }
    }
    .padding()

//    CustomDisclosureGroup<Text, View>(labelString: "Label", isExpanded: $isExpanded2) {
//      HStack {
//        Text("Content2")
//      }
//    }
//    .padding()
  }
}
解决方案

问题根源:原第二个初始化方法未对泛型参数LabelContent做约束,编译器无法推断Text(labelString)的类型就是LabelContent,因此必须添加强制转换,但这种转换不安全,且调用时需要手动指定泛型类型,导致代码无法正常运行。

正确的做法是给该初始化方法添加泛型约束,明确LabelContent必须是Text类型,让编译器自动推断类型,无需强制转换。

修改后的完整代码

public struct CustomDisclosureGroup<LabelContent: View, Content: View>: View {
    var label: LabelContent
    var content: Content
    @Binding var isExpanded: Bool
    
    public init(isExpanded: Binding<Bool>, @ViewBuilder label: () -> LabelContent, @ViewBuilder content: () -> Content) {
        self.label = label()
        self.content = content()
        self._isExpanded = isExpanded
    }
    
    // 添加泛型约束,限定LabelContent为Text类型
    public init(labelString: String, isExpanded: Binding<Bool>, @ViewBuilder content: () -> Content) where LabelContent == Text {
        self.init(isExpanded: isExpanded, label: { Text(labelString) }, content: content)
    }
    
    public var body: some View {
        DisclosureGroup(isExpanded: $isExpanded) {
            content
        } label: {
            label
        }
    }
}

调用方式

现在调用字符串标签的初始化方法时,无需手动指定泛型类型,直接正常调用即可:

CustomDisclosureGroup(labelString: "Label", isExpanded: $isExpanded2) {
    HStack {
        Text("Content2")
    }
}
.padding()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:03:36