I got this long error:
Function opaque return type was inferred as '_ConditionalContent<_ConditionalContent<some View, VStack<ForEach<[Dictionary<String, JSON>.Keys.Element], Dictionary<String, JSON>.Keys.Element, TupleView<(some View, some View)>?>>>, some View>' (aka '_ConditionalContent<_ConditionalContent<some View, VStack<ForEach<Array<String>, String, Optional<TupleView<(some View, some View)>>>>>, some View>'), which defines the opaque type in terms of itself
I think the issue is the "resursive" character of the rendering as the error log itself says also:
which defines the opaque type in terms of itself
If I replace in the second if-else-statement, as in comment you see, and return only a text, then I got no error.
@ViewBuilder
func showNode(json: JSON) -> some View {
if let v = json.get() as? String {
Text("\(v)").padding()
} else if let d = json.get() as? [String: JSON] {
VStack {
ForEach(d.keys.sorted(), id: \.self) { k in
if let v = d[k] {
Text("\(k)").padding()
showNode(json: v)
}
}
}
// Text("").padding()
} else {
Text("").padding()
}
}
Method is a recursive method, which should render a json tree.
And the JSON
public enum JSON {
case string(String)
case number(Float)
case object([String:JSON])
case array([JSON])
case bool(Bool)
func get() -> Any {
switch self {
case .string(let v):
return v
case .number(let v):
return v
case .object(let v):
return v
case .array(let v):
return v
case .bool(let v):
return v
}
}
}
And all I do render it on screen:
struct ContentView: View {
var data: JSON? = nil
init() {
updateValue()
return
}
mutating func updateValue() {
do {
if let jsonURL = Bundle.main.url(forResource: "user", withExtension: "json") {
let jsonData = try Data(contentsOf: jsonURL)
guard let d2 = try JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as? JSON else {
print("Can not convert to d2")
return
}
data = d2
}
} catch {
}
}
var body: some View {
VStack {
if let data = self.data {
showNode(json: data)
}
}
}