Добавление в массив с двух сетевых запросов


#1

typealias Photos = [Photo]

class Photo {

var photo:Data? = nil
var fullScreenPhoto:Data? = nil

}

static func fetchAlbumPhotos(albumId:Int,completion:@escaping(Photos) -> Void){

    AlamofireFetcherService.fetchPhotoURLs(albumId: albumId) { (photoURLs) in
                    
        var photos = Photos()

        for url in photoURLs{
            
            let photo = Photo()
        
            AlamofireFetcherService.fetchImageData(from: url.thumbnailUrl) { (imageData) in
                photo.photo = imageData
            }
            
            AlamofireFetcherService.fetchImageData(from: url.url) { (fullImageData) in
                photo.fullScreenPhoto = fullImageData
            }
            
            photos.append(photo)
            completion(photos)
        }
    }
}

Я получаю массив обьектов, у которых по два юрл адреса на картинку
Пытаюсь в комплишн для коллекшн вьюхи передать массив с обьектами Photo, имеющими уже данные фоток, но добавление в массив срабатывает раньше, чем назначение данных
Полагаю дело в асинхронности
Подскажите, как решить проблему


#2
  1. Если есть возможность повлиять на разработку серверной части API, просите что бы сделали получение всех данных одним запросом! Это самый лучший, правильный и best practice вариант для приложений.
  2. Если такой возможности нет, тогда вам нужно делать запросы поочередно, а не одновременно.
  3. Либо если хотите отправлять запросы одновременно, нужно сделать подобие семафора, но нужно будет так же придумать как отслеживать какой запрос выполнился и для какого элемента массива получены данные.

Хотя для 2 варианта семафор тоже нужен будет.

И вобще, я бы в любом случае не делал 2 и 3 вариант. Если это ваша практика, найдите другой сервис с API, т.к. отправлять запросы в цикле - это стрельба из пушки по воробьям. Запросов может быть сотни, будет много лишней нагрузки и прочего.


#3
  1. Согласен полностью, но такое уж тестовое (
    Отображать список альбомов из сети (запрос https://jsonplaceholder.typicode.com/albums). По тапу на элемент списка открывать экран подробного просмотра со списками фотографий в альбоме (например, запрос https://jsonplaceholder.typicode.com/photos?albumId=1). Отображать превью фотографий. По тапу на фото открывать ее в полном размере с возможностью масштабирования.
    2,3 Понял, значит правильно думал, спасибо большое

#5

Либо вот еще такой вариант может подойти, что бы не делать запросы в цикле


Через расширение в UIImageView, пусть она сама занимается загрузкой.
Там же можно использовать Alamofire для кеширования.

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

Или еще проще, используйте либу SDWebImage. Все как рукой снимет. Будет только один запрос и все.


#6

Еп, сначала так и сделал, через расширение, но вот как раз эти нюансы и смутили.

Мне там нужно еще сохранять в БД ( использовал Реалм )

“С экрана подробного просмотра альбома предусмотреть возможность сохранить альбом в БД устройства.
На второй вкладке приложения отображать список сохраненных альбомов, аналогично списку из сети. Сохранять не только данные альбома, но и всех фотографий альбома.”

А в случае с запросом на изображение в самой ячейке получается, что для функции сохранения всех этих изображений в БД, опять же приходится по циклу прогнать каждый запрос + чтобы открыть фуллСайз изображение - это еще запрос в функции на это
Поэтому решил попробовать реализовать, чтобы коллекшн вью уже сразу имел массив изображений

За SDWebImage спасибо, ща чекну


#7
  1. получаете данные для альбома
  2. делаете релоад коллекции
  3. в ячейку передаете элемент массива (модель)
  4. в классе ячейки передаете ссылку на превью imageView.sd_setImage(with url)
  5. при тапе на ячейку, передаете этот же элемент массива (модель) туда где будет большая картинка
  6. там где большая картинка так же отображаете ее bigImageView.sd_setImage(with url)

Только модель Photo будет иметь типы String в данном случае и получать Data больше не нужно.