Wojciech Syper
Wojciech Syper

Reputation: 31

SwiftUI How to fix "Unable to infer complex closure return type; add explicit type to disambiguate"

i don't know how to fix this error "Unable to infer complex closure return type; add explicit type to disambiguate". I tried already everythink (what i can ) and doesn't work

import SwiftUI  

struct ContentView: View {  

    @State var content: String = "start"  


    var body: some View {  

        VStack { // Unable to infer complex closure return type; add explicit type to disambiguate  

            self.content = try! String(contentsOf: URL(string: "http://zyglarski.pl/swift-http-docs/tinder_list.php")!)  

            var contentData = self.content.data(using: .utf8)  
            var jsDec = JSONDecoder()  
            var responce = try! jsDec.decode(Candidates.self, from: contentData!)  

            Text(responce)  
        }  
    }  
}  

struct ContentView_Previews: PreviewProvider {  
    static var previews: some View {  
        ContentView()  
    }  
}  


struct Candidates: Codable {  
    let candidates:[Candidate]  
}  
struct Candidate: Codable {  
    let filename: String  
    let name: String  
    let age: String  
    let distance: String  
    let match: String  
} 

Help, please

Upvotes: 2

Views: 2663

Answers (2)

cbjeukendrup
cbjeukendrup

Reputation: 3446

As an addition for Chris' answer:

Let's look a bit at closures. A "normal" closure, we can see for instance with .map { ... } with arrays, which applies a function on each element of the list, and returns a new list with the results, like this:

let myArray = [1, 2, 3, 4, 5]
let tenTimes = myArray.map { (element) -> (Int) in
    return element * 10
}
// tenTimes is [10, 20, 30, 40, 50]

(element) -> (Int) in means: we get a parameter and call it element so we can use it inside the closure, and the closure's return type is Int.

Often, we use a shorthand version for the second line of that little piece of code:

let tenTimes = myArray.map { element in

Swift can infer the return type in this case.

But since (I believe) Swift 5.1, there is a new rule: when the contents of the function/variable/closure is only one line of code, we don't need to explicitly write the word return. So in the case above, we could also say:

tenTimes = myArray.map { element in
    element * 10
}

Almost every {} you see in SwiftUI means that you are using a closure. That last rule about the return keyword is applied very often in SwiftUI.

But there is something else: the closures in SwiftUI are special @ViewBuilder closures. Therefore, you can put multiple Views inside another View, it's like having a function with multiple returns in it. But when you use other code, like a let statement, things get messed up. SwiftUI doesn't understand what you want.
Sometimes you can help it a little by using explicit return, but often the error just moves to another place. There is a chance that, after a lot of puzzling, you would get it working, but I can assure you, it won't be beautiful code. Therefore, I would choose Chris' solution.

Edit 2021: I was naïve about "functions with multiple return statements". Something more complex is going on. This video explains what exactly: https://developer.apple.com/videos/play/wwdc2021/10253/
This may also give clarification about why putting other statements in those special closures does not work.


If you want to read more about closures, here is a link to the official documentation: https://docs.swift.org/swift-book/LanguageGuide/Closures.html. Very interesting, but a lot of information!

Upvotes: 6

Chris
Chris

Reputation: 8091

please please read a swiftui beginner tutorial, because you made a lot of beginner mistakes.

and for quick help check this out:

struct ContentView: View {


    @State var content: String = "start"
    @State var responce : String = ""
    @State var candidates : Candidates = Candidates(candidates: [])

    var body: some View {

        VStack { // Unable to infer complex closure return type; add explicit type to disambiguate



            Text(responce)
                .onAppear() {
                    self.content = try! String(contentsOf: URL(string: "http://zyglarski.pl/swift-http-docs/tinder_list.php")!)

                    var contentData = self.content.data(using: .utf8)
                    var jsDec = JSONDecoder()
                    self.candidates = try! jsDec.decode(Candidates.self, from: contentData!)
            }

        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct Candidates: Codable {
    let candidates:[Candidate]
}
struct Candidate: Codable{
    let filename: String
    let name: String
    let age: String
    let distance: String
    let match: String
}

Upvotes: -1

Related Questions