'Индекс массива вне диапазона' в 'RefreshControl'

У меня есть TableView, где я получаю данные из api. Все работает нормально с извлечением / отображением данных и разбиением на страницы / бесконечным прокруткой. Однако, когда я пытаюсь использовать свой RefreshControl, он вылетает с ошибкой:

Индекс массива выходит за пределы диапазона

var theRefreshControl: UIRefreshControl! var results: [JSON]! = [] // more stuff.. func refresh(sender: AnyObject) { if isFirstLoad == false { self.results = [] currentPage = 1 getPosts() } self.theRefreshControl.endRefreshing() } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell : PostCell = tableView.dequeueReusableCellWithIdentifier("PostCell") as! PostCell cell.delegate = self print(indexPath.row) // check below. let post = self.results![indexPath.row] // 'array index out of range' here. } 

Чтобы получить более подробную информацию об ошибке, я попытался добавить print(indexPath.row) . То, что я получаю, я получаю от 0 до 10 при первой загрузке, а затем, как только я обновляюсь, это становится странным:

введите описание изображения здесь

Кроме того, когда я нажимаю на (i):

{длина = 2, путь = 0 – 9}

Интересно, что точно такой же подход работает и в моих других TableViewControllers, только этот прослушивается. В чем может быть проблема?


 func getPosts() { isLoading = true Alamofire.request(.GET, link & params: ["page":"\(currentPage ?? 1)"]) .responseJSON { response in // error checks if let data = json["data"].arrayValue as [JSON]? { self.lastPage = json["last_page"].int! self.currentPage = json["current_page"].int! if self.currentPage == 1 { self.results = data self.tableView.reloadData() } else { var currentCount = self.results!.count; var indxesPath : [NSIndexPath] = [NSIndexPath]() for result in data { indxesPath.append(NSIndexPath(forRow:currentCount,inSection:0)); self.results?.append(result) currentCount++ } self.tableView.insertRowsAtIndexPaths(indxesPath, withRowAnimation: UITableViewRowAnimation.Bottom) } 

Изменить: Обратите внимание, что я попробовал results.removeAll() а также results.removeAll(keepCapacity: false) в функции действия кнопки обновления, но не повезло. Я все еще получаю ту же ошибку и тот же журнал для `print (indexPath.row) – от 0 до 10 при первой загрузке и при обновлении, странно 6, 7, 8, [], 9

Swift 3.0 – та же проблема, решенная аналогично @mcclux, но с одним меньшим шагом.

Используйте встроенный UIRefreshControl. var refreshControl: UIRefreshControl! , то в viewDidLoad настройте его:

  refreshControl = UIRefreshControl.init() refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh") refreshControl.addTarget(self, action: #selector(yourViewControllerName.yourFunctionToCallOnRefresh), for: UIControlEvents.valueChanged) tableView.addSubview(refreshControl) 

Затем вы можете обернуть свой код в cellForRowAt indexPath с помощью

if !self.refreshControl.isRefreshing { ... }

Работала отлично для меня, когда она изо всех сил пыталась провалиться. Надеюсь это поможет!

У меня была аналогичная проблема; это было вызвано в моем случае вызовом tableView во время обновления, в период, когда содержимое было сброшено. Поскольку индекс был пустым в течение определенного периода времени, приложение иногда бросало индекс за пределы диапазона. Это не случалось каждый раз. Я решил это, создав boolean var (isRefreshing), который получает значение true, когда начинается обновление, а затем устанавливается значение false после завершения обновления. Внутри tableView() У меня есть оболочка для этой функции. В вашем случае это будет выглядеть так:

 override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { if !self.isRefreshing { let cell : PostCell = tableView.dequeueReusableCellWithIdentifier("PostCell") as! PostCell cell.delegate = self print(indexPath.row) // check below. let post = self.results![indexPath.row] // 'array index out of range' here. } } 

Изменить: вот как я его использую. Создание и возврат ячеек вне if:

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("SessionTableViewCell", forIndexPath: indexPath) as! SessionTableViewCell if !self.isReloading { ... } return cell } 

Решил мою проблему, удалив self.results = [] из функции refresh() . Интересно, что если я очистил массив до обновления, это создало проблему, но если я просто перезаписал данные в массиве, это сработает!

Я столкнулся с аналогичной проблемой, когда массив поддержки был опустошен, как то, что вы делали w / self.results = [] . По моему мнению, есть 2 дополнительных способа решения этой проблемы.

 //1. is to reload table view as soon as you empty the array func refresh(sender: AnyObject) { if isFirstLoad == false { self.results = [] self.tableView.reloadData() currentPage = 1 getPosts() } self.theRefreshControl.endRefreshing() } //2. is to delay the execution of the code inside the if scope to give enough time for the table view to get up to date on the count of the results array func refresh(sender: AnyObject) { if isFirstLoad == false { self.delayExecutionByMilliseconds(500) { self.results = [] currentPage = 1 getPosts() } } self.theRefreshControl.endRefreshing() } func delayExecutionByMilliseconds(_ delay: Int, for anonFunc: @escaping () -> Void) { let when = DispatchTime.now() + .milliseconds(delay) DispatchQueue.main.asyncAfter(deadline: when, execute: anonFunc) }