Загрузка образа хранилища Swift 4 Firebase в рамках цикла «For Loop» - PullRequest
0 голосов
/ 21 мая 2018

У меня есть моментальный снимок Firebase с несколькими возвращенными узлами:

Снимок экрана базы данных

И попробуйте использовать цикл for для его прохождения.В каждом цикле я хотел бы загрузить файл изображения из Firebase Storage:

let projectReviews = projectDB.queryOrdered(byChild: "contractorID").queryEqual(toValue: contractorID)

    projectReviews.observeSingleEvent(of: .value, with: { snapshot in

        for child in snapshot.children.allObjects as! [DataSnapshot] {
            guard let value = child.value as? [String: AnyObject] else { continue }
                if value["projectStatus"] as? String ?? "" == "Completed" && value["recommend"] != nil {

                counter += 1
                    print("this is how many times this for loop has go through \(counter) at \(child.key)")

                    //Fetch and display the data.

                    var downloadURL :String
                    downloadURL = "Projects/" + "\(child.key)" + "--00"
                    print("---" + downloadURL)
                    print("downloadURL before download---" + downloadURL )
                    var imgURL = self.storageRef.child("")
                    imgURL = self.storageRef.child(downloadURL)
                    print("downloadURL after assign download URL ---" + downloadURL )
                    imgURL.getData(maxSize: Int64(1 * 1024 * 2000), completion: { (data, error) in
                        if let error = error {
                            print(error)
                            print("===This is image Download error on=== \n")
                            print(counter)
                            print("\(downloadURL)")
                            return
                        } else {
                        //Do something

                        }
                    })

}

Как вы видите здесь, я поместил несколько команд печати, чтобы сообщить мне, что происходит с переменной downloadURL.

Проблема:

во 2-м цикле, переменная downloadURL, когда фактически пытается загрузить файл, все еще использует значение предыдущего цикла, даже если перед "getData" значение было правильным:

this is how many times this for loop has go through 1 at vzzzzzzzzzzzzzz----0001
---Projects/vzzzzzzzzzzzzzz----0001--00
downloadURL before download---Projects/vzzzzzzzzzzzzzz----0001--00
downloadURL after assign download URL ---Projects/vzzzzzzzzzzzzzz----0001--00
this is how many times this for loop has go through 2 at vzzzzzzzzzzzzzz----0002
---Projects/vzzzzzzzzzzzzzz----0002--00
downloadURL before download---Projects/vzzzzzzzzzzzzzz----0002--00
downloadURL after assign download URL ---Projects/vzzzzzzzzzzzzzz----0002--00
Error Domain=FIRStorageErrorDomain Code=-13010 "Object Projects/vzzzzzzzzzzzzzz----0001--00 does not exist."     UserInfo={object=Projects/vzzzzzzzzzzzzzz----0001--00, bucket=bafo-1c3c8.appspot.com, ResponseBody=<?xml version='1.0' encoding='UTF-8'?><Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Details>No such object: bafo-1c3c8.appspot.com/Projects/vzzzzzzzzzzzzzz----0001--00</Details></Error>, data=<3c3f786d 6c207665 7273696f 6e3d2731 2e302720 656e636f 64696e67 3d275554 462d3827 3f3e3c45 72726f72 3e3c436f 64653e4e 6f537563 684b6579 3c2f436f 64653e3c 4d657373 6167653e 54686520 73706563 69666965 64206b65 7920646f 6573206e 6f742065 78697374 2e3c2f4d 65737361 67653e3c 44657461 696c733e 4e6f2073 75636820 6f626a65 63743a20 6261666f 2d316333 63382e61 70707370 6f742e63 6f6d2f50 726f6a65 6374732f 76353756 5467595a 4c685170 7a57486a 4c306131 6b733150 494a6d31 52695339 61574631 4f6a5854 63635963 524b6453 67525a6f 54473832 2d2d2d2d 30303031 2d2d3030 3c2f4465 7461696c 733e3c2f 4572726f 723e>, NSLocalizedDescription=Object Projects/vzzzzzzzzzzzzzz----0001--00 does not exist., ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=404}
Projects/vzzzzzzzzzzzzzz----0001--00

, как вы видите из журнала, если я распечатаю переменную downloadURL в закрытии getData, она содержит предыдущее значение "vzzzzzzzzzzzzzz ---- 0001"

Это мой способделать поддержали?Если нет, то как я могу обойти это, чтобы изображение могло отображаться в одном цикле?

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Нашел решение.Это должно быть в состоянии применить ко всем случаям в этом асинхронных вызовов с базой данных Firebase.

Это решение состоит из двух частей.

Сначала определите функцию с обратным вызовом для запроса и сохранения данных в виде класса в массиве:

  func getList(callback: @escaping ((_ data:[reviewContent]) -> Void)) {
    var contentArray :[content] = [content]()
    let someDB = dbRef!.child("someDB")

    let returns = someDB.queryOrdered(byChild: "contractorID").queryEqual(toValue: someValue)

    returns.observe(.value, with: {(snapshot) in
        print(snapshot.childrenCount)

        for child in snapshot.children.allObjects as! [DataSnapshot] {
            guard let value = child.value as? [String: AnyObject] else { continue }

            let contentEntry = content()
            contentEntry.ID = child.key
            //store any additional values where defined in the class

            contentArray.append(contentEntry)

        }

        print("Array now has \(contentArray.count)")
        callback(contentArray)

    }) {(error) in print(error.localizedDescription)}
}

2-й, запустите эту функцию в viewDidLoad () и используйте функцию обратного вызова для использования записей массива с циклом for:

    getList { (data:[content]) in
        print("this is data from call back" )
        print(data)


        for contentEntry in data {
            print(contentEntry.ID)


                                    imgURL = self.storageRef!.child(contentEntry.ID)

                                    imgURL.getData(maxSize: Int64(1 * 1024 * 2000), completion: { (imageData, error) in
                                        if let error = error {
                                            print(error)
                                            print("===This is image Download error on=== \n")
                                            print("\(contentEntry.ID)")
                                            return
                                        } else {
                                            print("===This is image Download URL was used=== \n")
                                            print("\(contentEntry.ID)")
                                            print(imageData)
                                        }
                                    })
        }
    }

Надеюсь, это поможет.

Обратите внимание, что лучше всегоОпределите класс для данных, которые вы хотите сохранить в массиве в первой части.Это также делает перезвон во второй части намного проще.

0 голосов
/ 02 июня 2018

Я считаю, что проблема в сроках.У вас есть асинхронные вызовы, первый из которых относится к вашей базе данных FireBase.Вы запускаете цикл for в фигурных скобках этого, так что там нет проблем с синхронизацией, однако, тогда у вас есть асинхронный вызов в пределах цикла for.цикл for сгорает до начала асинхронного вызова.Вы должны использовать цикл for для создания массива URL-адресов, а затем в своем втором асинхронном вызове get data запустить второй цикл for, используя ваш массив URL-адресов.

...