-1

Im trying to wait for the function to process in order to show my image. I have try many things but none of this worked. I know this is an async function and basically i have to wait in order to get the right values but I dont know how to fix this function right here. I hope you can help me out. Thank you!

     func createListProductsGood(Finished() -> void) {

        refProducts.child("Products").queryOrderedByKey().observe(.childAdded, with: { snapshot in

            let prod = snapshot.value as! NSDictionary
            let active = snapshot.key
            let rejected = prod["NotInterested"] as! String
            let photoURL = prod["photoURL"] as! String
            var findit = false

           // print(rejected)

            if (rejected != self.userUID){
                //print(active)
                if rejected.contains(","){
                     var pointsArr = rejected.components(separatedBy: ",")
                        for x in pointsArr{
                                if x.trimmingCharacters(in: NSCharacterSet.whitespaces) == self.userUID {
                                   // print("dont show")
                                    findit = true
                                    return
                                }
                            }

                    if (findit == false){
                        if let url = NSURL(string: photoURL) {
                            if let data = NSData(contentsOf: url as URL) {
                                self.ProductId = active
                                self.productPhoto.image = UIImage(data: data as Data)
                            }}
                    }
                }else{
                    print(active)
                    if let url = NSURL(string: photoURL) {
                        if let data = NSData(contentsOf: url as URL) {
                            self.ProductId = active
                            self.productPhoto.image = UIImage(data: data as Data)

                        }}
                }


            }

               })

    finished()

}

Edited:

This is how my viewDidLoad looks like:

override func viewDidLoad() {
    super.viewDidLoad()
    setAcceptedOrRejected()
    createListProductsGood{_ in
    }


}



 func createListProductsGood(finished: @escaping (_ imageData: Data) -> Void) {

        refProducts.child("Products").queryOrderedByKey().observe(.childAdded, with: { snapshot in

            let prod = snapshot.value as! NSDictionary
            let active = snapshot.key
            let rejected = prod["NotInterested"] as! String
            let photoURL = prod["photoURL"] as! String
            var findit = false

           // print(rejected)

            if (rejected != self.userUID){
                //print(active)
                if rejected.contains(","){
                     var pointsArr = rejected.components(separatedBy: ",")
                        for x in pointsArr{
                                if x.trimmingCharacters(in: NSCharacterSet.whitespaces) == self.userUID {
                                   // print("dont show")
                                    findit = true
                                    return
                                }
                            }

                    if (findit == false){
                        if let url = NSURL(string: photoURL) {
                            if let data = NSData(contentsOf: url as URL) {
                                self.ProductId = active
                                DispatchQueue.main.async {
                                    self.productPhoto.image = UIImage(data: data as Data)
                                }
                            }}
                    }
                }else{
                    print(active)
                    if let url = NSURL(string: photoURL) {
                        if let data = NSData(contentsOf: url as URL) {
                            self.ProductId = active
                            DispatchQueue.main.async {
                             self.productPhoto.image = UIImage(data: data as Data)
                            }
                        }}
                }
        }
             })

}

This is my second method:

func setAcceptedOrRejected() {
    refProducts.child("Products").queryOrderedByKey().observe(.childAdded, with: { snapshot in

        let prod = snapshot.value as! NSDictionary

        if self.ProductId == snapshot.key{

            self.texto = prod["NotInterested"] as! String
            self.refProducts.child("Products").child(self.ProductId).updateChildValues(["NotInterested": self.texto + ", " + self.userUID])

        } })
}
Blazej SLEBODA
  • 8,936
  • 7
  • 53
  • 93

1 Answers1

-1

You should change:

func createListProductsGood(Finished() -> void) {

to:

func createListProductsGood(finished: @escaping (_ something: SomeType) -> Void) {

or to be more specific:

func createListProductsGood(finished: @escaping (_ imageData: Data) -> Void) {

then wherever in your function you get the image, you call

finished(imageData)

so you can pass the imageData through a closure to where its needed.

then you call this function like this:

createListProductsGood{ imageData in 
    ...
   let image = UIImage(data: imageData)

   // update UI from main Thread:
   DispatchQueue.main.async {
   self.productPhoto.image = image
   }
}

Also:

  • it's not convention to use Finished(), you should use finished()

  • using void is wrong. You must use Void or ()


If you're having problems with closures and completionHandlers, I recommend you first try getting your hands dirty with a simple UIAlertController. See here. Try creating an action with a closure, e.g. see here


EDIT :

Thanks to Leo's comments:

func createListProductsGood(finished: @escaping(_ imageData: Data?, MyError?) -> Void) {

let value: Data?
let error = MyError.someError("The error message")

    refProducts.child("Products").queryOrderedByKey().observe(.childAdded, with: { snapshot in

        let prod = snapshot.value as! NSDictionary
        let active = snapshot.key
        let rejected = prod["NotInterested"] as! String
        let photoURL = prod["photoURL"] as! String
        var findit = false

        // print(rejected)

        if (rejected != self.userUID){
            //print(active)
            if rejected.contains(","){
                var pointsArr = rejected.components(separatedBy: ",")
                for x in pointsArr{
                    if x.trimmingCharacters(in: NSCharacterSet.whitespaces) == self.userUID {
                        // print("dont show")
                        findit = true
                        return
                    }
                }

                if (findit == false){
                    if let url = NSURL(string: photoURL) {
                        if let data = NSData(contentsOf: url as URL) {
                            self.ProductId = active // REMOVE
                            self.productPhoto.image = UIImage(data: data as Data) // REMOVE
                            finished(data, nil) //ADD
                        }else{
                            finished(nil,error) //ADD
                        }
                    }
                }
            }else{
                print(active)
                if let url = NSURL(string: photoURL) {
                    if let data = NSData(contentsOf: url as URL) {
                        self.ProductId = active // REMOVE
                        self.productPhoto.image = UIImage(data: data as Data) // REMOVE
                        finished(data,nil) //ADD
                    }else{
                        finished(nil,error) //ADD
                    }
                }
            }

        }
    })
}

And then you call it like:

   createListProductsGood { imageData, error in guard let value = imageData, error == nil else { // present an alert and pass the error message return } 

   ...
   let image = UIImage(data: imageData)

   // update UI from main Thread:
   DispatchQueue.main.async { 
   self.ProductId = active

   self.productPhoto.image = image } }

Basically this way the createListProductsGood takes in 2 closures, one for if the image is present, another for if an error was returned.

mfaani
  • 33,269
  • 19
  • 164
  • 293