Не показывать tableView, пока грузятся данные

swift

#1

Всем привет! Такая задача -

У меня есть tableView, в ячейках которого только изображения, размеры которых равны размеру ячейки.

Необходимо, чтобы пока не загрузятся все ячейки со всеми изображениями, tableView не показывалось, а крутился activityIndicator.

Помогите, пожалуйста! Заранее, огромное спасибо! :slight_smile:


#2

У меня прям дежавю. Кажется был такой вопрос на форуме несколько месяцев назад. Попробуйте поискать.


#3

Если я Вас правильно понял, то можно же просто вьюху поверх поместить, а на нее activity indicator, когда все прогрузится, тогда можно удалить и вьюху и индикатор.


#4

Мне кажется он немного другое хочет.
К примеру есть таблица, мы отправили запрос на получение данных. Там мы получили на каждую ячейку ссылку на картинку. И пока все картинки не загрузятся в UIImageView, не показывать саму таблицу.


#5

Именно это я имею ввиду :slight_smile:


#6

Есть ли какие-либо решения?

Я вот думаю так затестить:

Построить логичкскую конструкцию, типа «если UIImageView.image == UIImage(named: “Bla-bla”), то loadingView.isHidden = false). Либо наблюдатель willSet поставить.


#7

Просто вот не знаю как отслеживать этот момент


#8

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

Минусы:

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

Другое решение, которое чаще делают разработчики, поместить индикатор загрузки в каждую ячейку по центру будущей картинки. Загрузку картинки делать внутри класса ячейки. Как только картинка загрузится, прятать индикатор и отображать картинку. Для этого лучше всего использовать библиотеку. К примеру SDWebImage. У вас будет кеширование картинок, если картинка долго грузится и ячейка пропала из виду (проскролилась), запрос в этой ячейке остановится, таким образом снизится сетевая нагрузка.


#9

Спасибо! Думаю, добавлю просто индикатор на каждую ячейку и фреймворком воспользуюсь :slight_smile:


#10

Привет.
1.

//Class
import UIKit

class ActivityIndicator {
    static let shared = ActivityIndicator()
    
    func customActivityIndicatory(_ viewContainer: UIView, startAnimate:Bool? = true) -> UIActivityIndicatorView {
        let mainContainer: UIView = UIView(frame: viewContainer.frame)
        mainContainer.center = viewContainer.center
        mainContainer.backgroundColor = UIColor.black
        mainContainer.alpha = 0.5
        mainContainer.tag = 789456123
        mainContainer.isUserInteractionEnabled = false
        
        let viewBackgroundLoading: UIView = UIView(frame: CGRect(x:0,y: 0,width: 80,height: 80))
        viewBackgroundLoading.center = viewContainer.center
        viewBackgroundLoading.backgroundColor = UIColor.darkGray
        viewBackgroundLoading.alpha = 0.5
        viewBackgroundLoading.clipsToBounds = true
        viewBackgroundLoading.layer.cornerRadius = 15
        
        let activityIndicatorView: UIActivityIndicatorView = UIActivityIndicatorView()
        activityIndicatorView.frame = CGRect(x:0.0,y: 0.0,width: 40.0, height: 40.0)
        activityIndicatorView.style =
            UIActivityIndicatorView.Style.whiteLarge
        activityIndicatorView.center = CGPoint(x: viewBackgroundLoading.frame.size.width / 2, y: viewBackgroundLoading.frame.size.height / 2)
        if startAnimate!{
            viewBackgroundLoading.addSubview(activityIndicatorView)
            mainContainer.addSubview(viewBackgroundLoading)
            viewContainer.addSubview(mainContainer)
            activityIndicatorView.startAnimating()
        }else{
            for subview in viewContainer.subviews{
                if subview.tag == 789456123{
                    subview.removeFromSuperview()
                }
            }
        }
        return activityIndicatorView
    }
    
    private init() { }
}

Инициализация
let activityIndicator = UIActivityIndicatorView(style: .gray)
3.
Запуск при загрузке VC
let _ = ActivityIndicator.shared.customActivityIndicatory(self.view, startAnimate: true)
4.
Выход когда данные загружены
let _ = ActivityIndicator.shared.customActivityIndicatory(self.view, startAnimate: false)
5.
Примечание:
Использую синглтон для получения данных и после всех манипуляций с данными добавляю пункт 4. все ок. Если что пиши) Удачи)