Unable to infer complex closure return type; add explicit type to disambiguate

Why am I getting this error while trying to use if statement twice ?

struct PostView: View {
    @EnvironmentObject var observedData : getData
    var shortcut = ""
    var body : some View{
            ScrollView(.vertical, showsIndicators: false) {
                VStack(alignment: .leading){
                    ForEach(observedData.datas){i in
                        if i.groupsShortcut == self.shortcut && i.pic!=""{ // here is the error position.
                            tweetCellTop(name: i.name, id: i.tagId, pic: i.pic, image: i.url, msg: i.msg)
                                tweetCellMiddle(pic: i.pic).padding(.leading, 60)
                            tweetCellBottom().offset(x: UIScreen.main.bounds.width / 4)
                }.padding(.bottom, 15)
                        Image(" user Image ").resizable().frame(width: 35, height: 35).clipShape(Circle()).onTapGesture {
                            print("slide out menu ....")

What does getData look like?

@ Lantua

class getData : ObservableObject{

    @Published var datas = [datatype]()
    @Published var top = [Topdatatype]()
    init() {
        let db = Firestore.firestore()
        db.collection("tweets").addSnapshotListener { (snap, err) in
            if err != nil{
            for i in snap!.documentChanges{
                if i.type == .added{
                    let id = i.document.documentID
                    let name = i.document.get("name") as! String
                    let msg = i.document.get("msg") as! String
                    let pic = i.document.get("pic") as! String
                    let url = i.document.get("url") as! String
                    let retweets = i.document.get("retweet") as! String
                    let likes = i.document.get("likes") as! String
                    let tagID = i.document.get("id") as! String
                    let groupsShortcut = i.document.get("groupsShortcut") as! String
                    DispatchQueue.main.async {
                        self.datas.append(datatype(id: id, name: name, msg: msg, groupsShortcut: groupsShortcut, retwetts: retweets, likes: likes, pic: pic, url: url, tagId: tagID))

Last one, datatype.

Btw, does the error occur when you added if statement, or only that it appears at if statement? Because the current compiler can have misleading error location for SwiftUI. If it happens right after you added if, it’d be more definite.

It does not appear when I check only once for example if i.pic != "" but if I add one condition more, this error appears and destroy everything.

I assume

if i.groupsShortcut == self.shortcut {

Works too?

Anyhow, as the error said, the compiler couldn’t guess the type of everything you typed in the allotted time. The way SwiftUI works, it needs to guess everything in body function in one go.

So if it is really because the whole function is too long, you can break it into multiple functions/compute properties.

But I’m suspecting that there is a wrong type than the one you intended in there simply because I’ve done longer functions and it works fine.

Any solution?


How to do this pleases? I am just beginner :(

Before we delve into that, does checking only once on the other side work?

if i.groupsShortcut == self.shortcut {

yes it works if I check if i.groupsShortcut == self.shortcut { alone or just if i.pic != "" but not both together

Ok, I think I found it, if you use exact same code as the first post (aka, copy-and-paste), it leads to incorrect operators

if i.groupsShortcut == self.shortcut && i.pic!=""{

turns into

if (i.groupsShortcut == self.shortcut) && ((i.pic!)=""){

but you want

if (i.groupsShortcut == self.shortcut) && (i.pic != "") {

Which can be fixed by proper spacing

if i.groupsShortcut == self.shortcut && i.pic != "" {

Note the space between i.pic and "". Swift operator is somewhat sensitive to whitespace before and after it. That's the only place you need to be wary of space really.

i am confusing now. Which is the correct variant ?

This one,

if i.groupsShortcut == self.shortcut && i.pic != "" {

It's generally good idea to put spaces between binary operator (a == b), but leave no space for unary operator (-a or b!, etc.)

On a side node, check out API Design Guideline.

In particular

Follow case conventions. Names of types and protocols are UpperCamelCase . Everything else is lowerCamelCase .

Thanks, what if I want to do like this if i.groupsShortcut == self.shortcut{
if i.pic != ""{

You mean like this?

if i.groupShortcut == self.shortcut {
  if i.pic != "" {

It's the same as what you're doing

if i.groupsShortcut == self.shortcut && i.pic != "" {

Either one is fine.

not really , I have to check if the shortcut are the same and then check if there is no pictures. :(

that's what it's doing, Once you're inside the first bracket, you already know the shortcuts are the same. Once's you're inside the second bracket, you also know that i.pic != "". Or maybe I'm missing something.

no in case of if i.groupsShortcut == self.shortcut && i.pic != "" { its be true if both are true. therefore I want to check first the shortcuts and then the pic