-1

In the following code, the function will return "Var" before the checkDayEqualsToDoc function can return a bool and change "Var". I've tried looking a lot of places for an answer and I keep seeing the same thing... use closures... use completions... etc. Are those the correct things to use in this case? And if so, how would I implement that?

func dotMarker(shouldShowOnDayView dayView: DayView) -> Bool {
    var Var:Bool = false
    let dDate = dayView.date.convertedDate()
    DispatchQueue.main.async {
        self.checkDayEqualsToDoc(date: dayView.date.convertedDate()!){ (bool, error) in
            Var = bool
        }
    }
    return Var
}

Here is the checkDayEqualsToDoc function:

func checkDayEqualsToDoc(date: Date, completionHandler:@escaping (Bool, Error?) -> Void){
    var Variable = false
    let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: date)
    let btRef = db.collection("bomtracking")

    let myDate = date
    let startOfDate = myDate.startOfDay
    let endOfDate = myDate.endOfDay
    let dateAtBeginning = date.firstSecondInDay()
    let dateAtEnd = date.lastSecondInDay()
    let query = btRef
        .whereField("UID", isEqualTo: UID)
        .whereField("timestamp", isGreaterThan: dateAtBeginning)
        .whereField("timestamp", isLessThan: dateAtEnd)

    DispatchQueue.main.async {
        query.getDocuments(){ (querySnapshot, err) in
            if let err = err {
                print("error getting documents: \(err)")
            } else {
                for document in querySnapshot!.documents{
                    let curValid = document.get("valid")
                    let curValidA = Bool(curValid as! Bool)
                    if curValidA == true {
                        let curdoc = document.get("timestamp")
                        let curdocDate = self.dateConversion(curdoc as! Date)
                        let dateConverted = self.dateConversion(date)
                        if curdocDate == dateConverted {
                            Variable = true
                            break
                        }
                        else {
                            Variable = false
                        }
                    }
                }
                completionHandler(Variable, nil)
            }
        }
    }
}
}
Andrew Wang
  • 55
  • 1
  • 3
  • 10

1 Answers1

0

When a function is asynchronous, you don't want to return the value, you want to pass it back in a completion.

func dotMarker(shouldShowOn dayView: DayView, completion: @escaping (Bool)->Void) {
    let dDate = dayView.date.convertedDate()
    DispatchQueue.main.async {
        self.checkDayEqualsToDoc(date: dayView.date.convertedDate()!){ (bool, error) in
            completion(bool)
        }
    }
}

Is what this would look like. When the checkDaysEqualsToDoc finishes, it calls its own completion, which is where the (bool, error) in comes from. In that completion, you have the value you want dotMarker to "return", so you call your completion handler with that bool value.

Two things though:

  1. Why are you putting checkDayEqualsToDoc in an async thread?

  2. Variable names should always start lowercased, and should be more descriptive than Var

Jake G
  • 1,185
  • 9
  • 19