1

I've been working on a SwiftUI project that generates UIs based on Server responses using JSON

In order to do that I have created a FormBuilder Now I want to show various types of custom fields like TextField, DateField, TextArea all fields have

text, title, etc as common properties but will have different Validating procedures

in order to program this,

I have used a protocol name "FormField", "SectionView" struct to load fields, some structs as Fields comforting to FormField and "FieldView" struct to load different Fields.

In the FieldView protocol I'm getting following error when I try to show various Views based on the type I get via json

I Have commented the line that shows the error in FieldView class

Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type

Can anyone help me to find a work around with this Any help will be so much appreciated !

FormField Protocol

protocol FormField : View {

var id : String! { get set }
var title : String? { get set }
var placeholder : String? { get set }
var text : String? { get set }
var validation : String? { get set }
var keyboardType : String? { get set }

init(json : JSON)

func validate()
func showError()
func isValid() -> Bool 
}

FieldView struct

Have commented the line that shows the error

struct FieldView: View {

private let TEXT = "text"
private let TEXTAREA = "textarea"
private let RADIO = "radio"
// could have more type

let id = UUID().uuidString
private var type : String!
private let fieldJson : JSON

init(json : JSON) {
    self.type = json["type"].stringValue
    self.fieldJson = json
}

var body: some View {
    field
}

private var field : some FormField{ 
// Errors Comes from above Line
    
    if type == TEXT {
        FormTextField(json: fieldJson)
    }
    if type == TEXTAREA {
        FormTextArea(json: fieldJson)
    }
    if type == RADIO {
        FormRadio(json: fieldJson)
    }
 }
 func validate() {
    field.validate()
}

func showError() {
    field.showError()
}

func  isValid() -> Bool{
    return field.isValid()
}
}

FormTextField struct

struct FormTextField: FormField {

var id : String!
var title : String?
var placeholder : String?
@State var text : String?
var validation : String?
var keyboardType : String?

init(json: JSON) {
    self.id = json["id"].string
    self.title = json["name"].string
    self.placeholder = json["placeholder"].string
    self.text = json["text"].string
    self.validation = json["validation"].string
    self.keyboardType = json["keyboardType"].string
}

var body: some View {
    Text("Text Field: \(title!)")
        .font(.headline)
        .padding()
        .background(Color.red)
}

func validate() {
    if title!.isEmpty {
       print("FormTextField Error")
    }
}

func showError() {
    
}

func  isValid() -> Bool{
    return title!.isEmpty && text!.isEmpty
}
}

FormTextArea struct

struct FormTextArea: FormField {

var id : String!
var title : String?
var placeholder : String?
@State var text : String?
var validation : String?
var keyboardType : String?

init(json: JSON) {
    self.id = json["id"].string
    self.title = json["name"].string
    self.placeholder = json["placeholder"].string
    self.text = json["text"].string
    self.validation = json["validation"].string
    self.keyboardType = json["keyboardType"].string
}

var body: some View {
    Text("Text Area: \(title!)")
        .font(.headline)
        .padding()
        .background(Color.red)
}

func validate() {
    print("Form Text Area")
}

func showError() {
    
}

func  isValid() -> Bool{
    return title!.isEmpty
}
}

FormRadio and other Fields also as same as this

Following SectionView struct was used to add fields inside of a VStack

SectionView struct

struct SectionView: View {

var id = UUID().uuidString
public var title : String?
public var fields = [FieldView]()

init(json : JSON) {
    self.title = json["sectionName"].string
    fields = (json["fields"].array ?? []).map({return FieldView.init(json: $0)})
}

var body: some View {
    VStack{
        Text(title ?? "Section")
            .font(.title)
        ForEach(fields,id:\.id){field in
            field
        }
    }
    .padding()
}
}
  • 1
    Have you tried to add `return` statements as the error suggests? By the way consider to drop `SwiftyJSON`. It's outdated for a long time in favor of built-in `Codable` – vadian Sep 08 '22 at 16:13
  • 1
    I tried it but it shows "Function declares an opaque return type, but the return statements in its body do not have matching underlying types" I also tried to making field a viewBuilder with @ViewBuilder without return inside if statements then I get this error "Return type of property 'field' requires that 'TupleView<(FormTextField?, FormTextArea?, FormRadio?)>' conform to 'FormField' " – Naleesh Jeffrey Sep 08 '22 at 16:23
  • 1
    Try `private var field : some View & FormField { ...` and add `return` statements. – vadian Sep 08 '22 at 16:29
  • 1
    @vadian Thank you for replying by the way after adding mentioned code I get this error **Function declares an opaque return type, but the return statements in its body do not have matching underlying types** Inside `private var field : some View & FormField { ...` I want to return Various FormFields like `FormTextField , FormTextArea, FormRadio` if I return only one type its okay but when I return various type I get the error FYI: all FormTextField , FormTextArea, FormRadio structs have confirmed to FormField Protocol – Naleesh Jeffrey Sep 10 '22 at 13:54

0 Answers0