如何为自定义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
相关产品推荐
相关产品推荐

