получить данные из FirebaseStorage в структуре - PullRequest
0 голосов
/ 04 мая 2020

Вот мой вызов: у меня есть структура. Это инициализируется с помощью documentSnapshot из FirebaseDatabase. Struct возвращает массив, который затем заполняется в представлении коллекции

Это работало нормально, пока я не попытался добавить два изображения в массив. Они хранятся в Firebase Storage. Ключи ссылок передаются в структуру при инициализации (они есть, это я проверял). Однако, когда myArray создан, изображений там нет. Там нет сообщения об ошибке. Все остальные части структуры / массива работают нормально (расчет расстояния и т. Д. c.)

Спасибо всем за помощь

struct myStruct {

    var myArray = [Any]()

    init?(Name: String, Amount: String, Description: String, SecondName: String, RID: String, GeoPoint: GeoPoint, DID: String) {

        var location = CLLocation()
        var myArray = [Any]()
        var distance: Double
        var imageA = UIImage()
        var imageB = UIImage()

        let refA = Storage.storage().reference().child("Images").child(todayDate).child(DID)
        refA.getData(maxSize: 1000 * 1240 * 1240) { data, error in
            if let error = error {
                print(error.localizedDescription)
            } else {
                imageA = UIImage(data: data!)!
            }
        }

        let refB = Storage.storage().reference().child("Icons").child(RID)
        refB.getData(maxSize: 1000 * 1240 * 1240) { data, error in
            if let error = error { print(error.localizedDescription)
                imageB = (UIImage(named: "DefaultIcon.png") as UIImage?)!
            } else {
                imageB = UIImage(data: data!)!
            }
        }

        location = CLLocation(latitude: GeoPoint.latitude, longitude: GeoPoint.longitude)
        distance = round(location.distance(from: userLocation)/10)*10


        myArray = [Name, Amount, Description, SecondName, String(Int(distance)), GeoPoint, imageA, imageB]

        self.menuItem = menuItem
    }
}

1 Ответ

0 голосов
/ 04 мая 2020

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

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

В целом, однако, было бы хорошей идеей не допускать такие асинхронные задачи с данными вне структуры init, и вместо этого выполняйте их в любом классе, который отвечает за создание и управление вашими структурами. Затем извлеченные изображения могут быть переданы в структуру в качестве параметров инициализации.

Вот как вы могли бы go рассказать об этом, продемонстрировав это немного отвлеченно:

Возможно, вы в данный момент находитесь где-то в вашем закодируйте объект с помощью функции, которая создает и хранит MyStruct s, аналогичный следующему:

func loadMyStruct() {
    self.myStruct = MyStruct(...)
}

Лучшей альтернативой этой функции создания структуры будет:

func loadMyStruct(completion: @escaping ()->Void) {
        DispatchQueue(label: "MyStructDataFetch", attributes: .concurrent).async { [weak self] in // don't block main thread waiting for data tasks to finish
            let dispatchGroup = DispatchGroup() // since we're waiting on two parallel async tasks, we can use a DispatchGroup to group them together

            var imageA: UIImage?
            var imageB: UIImage?

            dispatchGroup.enter() // enter DispatchGroup
            let refA = Storage.storage().reference().child("Images").child(todayDate).child(DID)
            refA.getData(maxSize: 1000 * 1240 * 1240) { data, error in // start 1st data task

                if let error = error {
                    ...
                } else {
                    imageA = UIImage(data: data!)!
                }

                dispatchGroup.leave() // 1st task is done; leave DispatchGroup
            }

            dispatchGroup.enter() // enter DispatchGroup
            let refB = Storage.storage().reference().child("Icons").child(RID)
            refB.getData(maxSize: 1000 * 1240 * 1240) { data, error in // start 2nd data task

                if let error = error {
                    ...
                } else {
                    imageB = UIImage(data: data!)!
                }
                dispatchGroup.leave() // 2nd task is done; leave DispatchGroup
            }

            let _ = dispatchGroup.wait(timeout: DispatchTime.distantFuture) // wait for all tasks to be done, then...

            self?.myStruct = MyStruct(imageA: imageA, imageB: imageB, ...) // ... pass the finished images to MyStruct constructor
            completion() // Optional: notify observer (e.g. UI) that "MyStruct" is now ready to use
        }
    }

init структуры изменен соответственно:

init?(imageA: UIImage?, imageB: UIImage?, ...) {
 ...
...