Trying to create a struct that returns a custom textfield according to the type selected... However, I get this error:
Function declares an opaque return type 'some View', but the return statements in its body do not have matching underlying types
I have already done this successfully with a Text() but apparently the TextField() works differently given that I will be accepting input by the user.
See code below:
import SwiftUI
/// The types of AtomsTextField's
enum AtomsTextFieldType {
case roundedBorder
case `default`
}
/// A struct that returns an AtomsTextField
struct AtomsTextField: View {
/// The text entered into the AtomsTextField
@Binding var text: String
/// The AtomsTextField type
let type: AtomsTextFieldType
/// The body displaying the AtomsTextField
var body: some View {
generateAtomsTextField(text: text, type: type)
}
/// Generates an AtomsTextField according to the type that was passed in
/// - parameter text: The text the AtomsTextField contains
/// - parameter type: An AtomsTextFieldType used to determine what AtomsTextField will be returned
private func generateAtomsTextField(text: String, type: AtomsTextFieldType) -> some View {
// Returning an AtomsTextField according to the type given
switch type {
case .roundedBorder: return TextField("Type here", text: $text).textFieldStyle(.roundedBorder)
case .default: return TextField("Type here", text: $text)
}
}
}
Any suggestions why and how to fix it?
You can simply use @ViewBuilder in front of your function to evaluate the results and return the view. You need to remove the "return"s from the function to use @ViewBuilder also. Effectively it causes the view to be "evaluated" each time the function is called much like the body.
Often having to use @ViewBuilder is a bit of a "code smell" and ideally I would put that view in to its own view struct and pass the variable in to avoid this, but this is incredibly simple. Its always a bit of a trade off.
@ViewBuilder private func generateAtomsTextField(text: String, type: AtomsTextFieldType) -> some View {
// Returning an AtomsTextField according to the type given
switch type {
case .roundedBorder:
TextField("Type here", text: $text).textFieldStyle(.roundedBorder)
case .default:
TextField("Type here", text: $text)
}
}