UICollectionView бесконечный свиток - PullRequest
0 голосов
/ 05 февраля 2019

Я искал эту тему, но не могу найти решение по моей проблеме. Это моя функция loadData, которая может получать данные из объекта JSON

 @IBOutlet weak var collectionVitrin: UICollectionView!

 var vitrinDecodePost = [VitrinDecode]() // Decodable

 func loadDatas(limit : Int) {

    guard let url = URL(string: "my Url") else { return }
    let session = URLSession.shared
    let request = NSMutableURLRequest(url: url as URL)
    request.httpMethod = "POST"
    let paramString = "limit=\(limit)"
    request.httpBody = paramString.data(using: String.Encoding.utf8)

    let task = session.dataTask(with: request as URLRequest) {
        (data, response, error) in
            guard let _:NSData = data as NSData? , let _:URLResponse = response, error == nil else {

                print("Mistake")
                return
            }

            guard let data = data else { return }
            do {

                let abc = try JSONDecoder().decode([VitrinDecode].self, from: data)
                self.vitrinDecodePost = abc

                DispatchQueue.main.async {

                    self.collectionVitrin.reloadData()
                }

            } catch { print(error)}

    }
    task.resume()
}

Я запускаю эту функцию в моем ViewDidLoad:

var deger : Int = 10

override func viewDidLoad() {
    super.viewDidLoad()
    loadData(limit: deger)
}

Когда прокрутка заканчивается, я хочу добавить больше данных, поэтому я добавил функцию willDisplay

func collectionView(_ collectionView: UICollectionView, 
numberOfItemsInSection section: Int) -> Int {

    return self.vitrinDecodePost.count
}

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

    let lastindex = self.vitrinDecodePost.count - 1
    if indexPath.row == lastindex{

        loadDatas(limit: 20)
        self.collectionVitrin.reloadData() 


    }

}

Когда страница загружена, 10 элементов отображаются в моих ячейках, но когда я достигаю конца страницы (последний индекс), представление коллекцииничего не отображатьВ моих коллекциях должно быть 20 предметов.Что я забыл?

1 Ответ

0 голосов
/ 06 февраля 2019

Вы должны удалить self.collectionVitrin.reloadData(), вызываемый сразу после LoadDatas(limit: 20) в вашей функции willDisplay.

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

Прежде всего, я бы посоветовал вам изменить свой вызов API.Вам следует сохранить ограничение на количество элементов, отправляемых обратно из каждого вызова API, но также реализовать переменную смещения.Это гораздо эффективнее.

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

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

 @IBOutlet weak var collectionVitrin: UICollectionView!
 var limitPerCall: Int = 10
 var isLoadindNewData = false
 var shouldLoadMoreData = true

 var vitrinDecodePost = [VitrinDecode]() // Decodable

 func loadDatas(limit : Int, offset: Int) {

     guard let url = URL(string: "my Url") else { return }
     let session = URLSession.shared
     let request = NSMutableURLRequest(url: url as URL)
     request.httpMethod = "POST"
     let parameters = ["limit": "\(limit)", "offset": "\(offset)"] as Dictionary<String, String>
     guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else { return }
     request.httpBody = httpBody

     let task = session.dataTask(with: request as URLRequest) { [weak self]
         (data, response, error) in
         guard let strongSelf = self, let _:NSData = data as NSData? , let _:URLResponse = response, error == nil else {

            print("Mistake")
            return
        }

       /// No More data to gather stop making api calls
        guard let data = data else { 
           strongSelf.shouldLoadMoreData = false
           return 
        }
        do {

            let abc = try JSONDecoder().decode([VitrinDecode].self, from: data)
            strongSelf.vitrinDecodePost.append(contentsOf: abc)

            //// Reload the new data and and indicates that api call can be 
            made again
            DispatchQueue.main.async {
                strongSelf.isLoadingNewData = false
                strongSelf.collectionVitrin.reloadData()
            }

        } catch { print(error)}

}
task.resume()
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection 
    section: Int) -> Int {

    return self.vitrinDecodePost.count
}

func collectionView(_ collectionView: UICollectionView, willDisplay cell: 
    UICollectionViewCell, forItemAt indexPath: IndexPath) {

    let lastindex = self.vitrinDecodePost.count - 1
    if indexPath.row == lastindex && !isLoadindNewData && shouldLoadMoreData {
        /// Forbids multiple api calls to happen at the same time
        isLoadindNewData = true
        loadDatas(limit: limitPerCall, offset: vitrinDecodePost.count)
    }

}

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

Best

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...