Swift 4: разбиение на страницы с использованием данных из массива для вызова API в качестве пользовательских прокруток - PullRequest
2 голосов
/ 22 марта 2019

Фон

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

Я использую базу данных Firestore для хранения идентификаторов объектов на моем конце.

Текущая реализация

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

  1. Получить идентификаторы объектов, которые будут использоваться для вызовов API
var objectIds: [String] = []
var chunkedObjectIds: [[String]] = []
var objects: [Array] = []
var offset: Int = 0

override func viewDidLoad() {
    super.viewDidload()

    getObjectIds()

 }

func getObjectIds() {
    // get objects IDs and store then in objectIds from the Firestore database
    // setup the .addSnapshotLister so the query is triggered whenever there is a change in the data on Firestore for the collection

    return chunkedObjectIds

    // when finished, get the first 10 objects from the 3rd party API

    fetchObjects()

}
  1. Возьмите массив идентификаторов объектов, разбейте его на массивы массивов (много по 10) и выполните вызов API для первых 10
func fetchObjects() {

     // split objectIds array in array of arrays, in lots of 10
     // chunkedObjectIds is set here

     // request the objects for the first 10 ID numbers

    Alamofire.request(… parameter with first 10 object ids …) (objects) in {

        // save objects

        // increment the offset
        offset += 1
    }

}
  1. Визуализация данных в ячейках UITableView

  2. Используйте следующий метод для загрузки дополнительных данных из стороннего API:

 func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

        let lastRow = objects.count 

        var parameters = [String: Any]()

        if indexPath.row == lastRow {
            if !(offset == self.chunkedObjectIds.count) {

                // process the next batch from the array
                parameters["id-numbers"] = self.chunkedObjectIds[offset].map{String($0)}.joined(separator: ",")

                Alamofire.request(… paramaters: parameters) { (objects) in
                    for item in 0..<objects.count {
                        let indexPath = IndexPath(row: item + self.objects.count, section: 0)
                        self.paths.append(indexPath)
                    }
                    self.objects.append(contentsOf: objects)
                    self.tableView.beginUpdates()
                    self.tableView.insertRows(at: self.paths, with: .automatic)
                    self.tableView.endUpdates()
                    self.paths.removeAll()
                    self.offset += 1
                }
            }
        }
    }
  1. Добавление или удаление объектов:

    • Идентификатор объекта добавляется или удаляется из базы данных Firestore
    • ObjectIds, chunkedObjectIds, смещение и объекты очищаются
    • Слушатель запускает чтение данных, и процесс повторяется

Проблема и вопрос

Это хорошо работает для загрузки исходных данных. Но при добавлении происходит дублирование (и иногда сбой). При удалении приложения происходит сбой из-за исключений вне диапазона.

Это правильный шаблон для использования в первую очередь? Если да, то что мне не хватает для обработки дел после первой загрузки, в частности, добавления и удаления новых идентификаторов объектов.

Редактировать

Я изменил реализацию на основе отзывов в комментариях. Итак, теперь процесс выглядит так:

  1. Настройка прослушивателя для получения данных из Firestore
  2. Цикл по идентификаторам объектов из Firestore, и пока счетчик <10 или мы достигаем object.count - Теперь я сохраняю следующее смещение, и в следующий раз, когда он вызывает этот метод, я запускаю цикл из следующего смещения с тем же в то время как условия </li>
  3. Извлечение объектов из стороннего API
  4. Я продолжал использовать метод willDisplay cell для запуска загрузки большего количества данных - казалось, он работал более надежно, чем метод scrollDidEnd.

Так что теперь приложение больше не падает. Есть некоторые проблемы со слушателем Firestore, но я опубликую это как отдельный вопрос.

...