# #swift #firebase #image
Вопрос:
В моем приложении будут списки изображений, как показано в приведенном ниже примере:
Чтобы получить отдельное изображение из firebase, я определил ViewModel
класс с одним изображением в качестве UIImage
свойства. Затем соответствующее представление может обновиться с учетом опубликованных изменений ViewModel
. Имея несколько-и фактически произвольное количество-изображений в списке, я не думаю, что предоставление каждому из них своего собственного ViewModel
будет эффективным, особенно потому, что я представляю, что мне придется ForEach
перебирать каждую ссылку на изображение и создавать ViewModel
внутри родительского представления. Это кажется проблематичным, потому что всякий раз, когда родительское представление воссоздается, я выполняю операцию O(n) для создания и инициализации моделей представлений для каждого изображения, не говоря уже о времени, необходимом для повторной выборки.
Есть ли способ извлечь несколько изображений из одного ViewModel
, сохранив их как [UIImage]
? Я бы, конечно, дал этому ViewModel
массив ссылок. В качестве альтернативы, какую архитектуру вы бы предложили для эффективной выборки любого количества изображений из firebase с учетом массива (неизвестного размера) ссылок на хранилище?
Я могу предоставить более подробную информацию / код по мере необходимости.
Кажется, это работает…
class MultipleImageFetcher: ObservableObject { var firebaseManager: FirebaseManager var imageDictionary: [String: UIImage] = [:] @Published var isReady = false init(_ firebaseManager: FirebaseManager) { self.firebaseManager = firebaseManager } func fetchAllImages(references: [String]) { for refID in references { fetchIndividualImage(id: refID, totalNum: references.count) } } func fetchIndividualImage(id: String, totalNum: Int) { let ref = getRefURL(uid: id) ref.getData(maxSize: 2051240) { data, error in if let error = error { print("Error: (error)") return } self.imageDictionary[id] = UIImage(data: data!) self.checkIsReady(num: totalNum) } } func getRefURL(uid: String) -gt; StorageReference { return firebaseManager.STORAGE.reference().child(uid) } func checkIsReady(num: Int) { if imageDictionary.count == num { self.isReady = true } else { self.isReady = false } } } struct ImageView: View { @ObservedObject var fetcher: MultipleImageFetcher init(_ firebaseManager: FirebaseManager) { self.fetcher = MultipleImageFetcher(firebaseManager) } var body: some View { Button { fetcher.fetchAllImages(references: ["KXKFM94sk5OTyld2VsCQdhijd6m1", "MtgRaKMwyQfYX2uxuHs3iH3pLB52"]) } label: { Text("Load Image") } if fetcher.isReady { Text("Is Ready") } else { Text("Loading...") } } }
Комментарии:
1. Да, вы определенно можете получить несколько изображений в одной модели представления, и да , вы можете сохранить их как
[UIImage]
, но реально, вы, вероятно, захотите сохранить их как пару ключ/значение, чтобы знать, к какой ячейке они принадлежат. Другими словами,[UUID:UIImage]
или что-то в этом роде. Возможно, вы также захотите изучить возможность кэширования результатов (NSCache
?)2. Какой вызов функции я должен выполнить в Firebase? Я предполагаю, что это еще не все,
ref.getData()
но в цикле for… И да, кэширование определенно у меня на уме…3. Нет, на самом деле в этом нет ничего особенного-есть, если вас волнует, когда данные вернутся (это означает, что должно произойти что-то последовательное).
4. Хорошо, я поиграю с этим подходом
5. Я предлагаю вам изучить Combine-это будет более надежное решение для загрузки конвейера и обработки ошибок