Неустранимая ошибка: индекс вне диапазона, из-за повторного нажатия кнопки «Мне нравится» и «Сердце» - PullRequest
1 голос
/ 16 июня 2019

Когда я снова и снова нажимаю кнопки «Мне нравится» и «Сердце», приложение вылетает и говорит: «Неустранимая ошибка: индекс вне диапазона».

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) - > Int {
    return activityArray.count
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) - > UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "activityCell") as!StreamActivityTableViewCell

    cell.likeButton.tag = indexPath.row
    print("....\(cell.likeButton.tag)")
    cell.heartButton.tag = indexPath.row
    cell.likeButton.addTarget(self, action: #selector(liked(sender: )),
        for: .touchUpInside)
    cell.heartButton.addTarget(self, action: #selector(loved(sender: )),
        for: .touchUpInside)

    return cell

}




@objc func liked(sender: UIButton) {
    let likebutton = sender.tag

    print("---- \(likebutton)  ... \(sender.tag)")
    let headers = ["Authorization": "Bearer \(UserDefaults.standard.string(forKey: "
        token ")!)"
    ]
    let parameters: Parameters = [
        "activity_id": activityArray[sender.tag].id!
    ]
    print(parameters)
    Alamofire.request(Constants.likedURL, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).validate().responseString {
        response in
            switch (response.result) {
                case.success(_):
                    if (response.result.isSuccess) {
                        self.activityArray.removeAll()
                        self.activityShown()
                    }
                    case.failure(_):
                        print("Error message:\(response.error!.localizedDescription)")
                        let alert = UIAlertController(title: "Sorry", message: "\(response.error!.localizedDescription)", preferredStyle: UIAlertController.Style.alert)
                        alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
                        self.present(alert, animated: true, completion: nil)
                        break
            }
    }
}





 func activityShown(){

        SVProgressHUD.show()
                    let headers = ["Authorization":"Bearer \(UserDefaults.standard.string(forKey: "token")!)"]

                    Alamofire.request(Constants.activitiesURL,method: .get,   encoding: JSONEncoding.default, headers: headers).responseJSON { response in

                        if response.result.isSuccess {
                            let ActivityJSON : JSON = JSON(response.result.value!)

                            let activityData = ActivityJSON["data"].arrayValue
                            let commentData = ActivityJSON["data"].arrayValue
                            for value in activityData {
                                let activity = Activity()
                                activity.name = value["name"].stringValue
                                activity.content = value["content"].stringValue
                                activity.published = value["published"].stringValue
                                activity.thumbnail = value["users"]["photo_thumb"].stringValue
                                activity.likesCount = value["likes_count"].intValue
                                activity.liked = value["liked"].intValue
                                activity.heartCount = value["heart_count"].intValue
                                activity.hearted = value["hearted"].intValue
                                activity.commentsCount = value["comments_count"].intValue
                                activity.commented = value["commented"].intValue
                                activity.id = value["id"].intValue
                                activity.currentID = value["users"]["user_id"].intValue
                                self.activityArray.append(activity)
                                SVProgressHUD.dismiss()

                            }

                            self.tableView.reloadData()
                            self.refreshControl.endRefreshing()
                        }
                        else {
                            print("Error \(String(describing: response.result.error))")
                        }
                    }
    }

Здесь я использую Observer, беру index.row из sender.tag, когда я нажимаю кнопку «Мне нравится» или «Сердце», этот API срабатывает и дает ответ. Когда я нажал больше, чем один раз, чем приложение вылетает.

1 Ответ

0 голосов
/ 16 июня 2019

Почему вы делаете это на удачу?

self.activityArray.removeAll ()

При следующем вызове этой функции вы будете индексировать в массив

"activity_id": activityArray [sender.tag] .id!

Но он будет пустым в зависимости от кода, который вы показали

Если activityArray меняется и кажется, что он используется для строк таблицы, вам нужно вызвать tableView.reloadData(), чтобы очистить таблицу

Редактировать - после просмотра обновленного кода.

Вы неправильно поняли

  1. Вы удаляете данные, прежде чем узнаете, есть ли у вас новые данные
  2. Вы перезагружаете данные в фоновом потоке - они всегда должны быть в основном потоке

Итак,

  1. Удалить строку self.activityArray.removeAll() в liked(sender:)
  2. Добавьте эту строку сюда
if response.result.isSuccess {
   let ActivityJSON : JSON = JSON(response.result.value!)



   //// HERE is where we know we are replacing the data
   self.activityArray.removeAll()


   let activityData = ActivityJSON["data"].arrayValue
   let commentData = ActivityJSON["data"].arrayValue

И, наконец,

self.tableView.reloadData()
self.refreshControl.endRefreshing()

Этот код должен быть таким

DispatchQueue.main.async {
   self.tableView.reloadData()
   self.refreshControl.endRefreshing()
}

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

РЕДАКТИРОВАТЬ: Как отметил Клаус в своем комментарии, лучшим подходом может быть использование deleteRows / insertRows и executeBatchUpdates

Я рекомендую вам сначала получить все, что работает с reloadData () - затем прочитайте документы Apple для https://developer.apple.com/documentation/uikit/uitableview/1614960-deleterows и https://developer.apple.com/documentation/uikit/uitableview/1614879-insertrows и https://developer.apple.com/documentation/uikit/uitableview/2887515-performbatchupdates и, возможно, посмотрите этот урок: https://www.youtube.com/watch?v=MC4mDQ7UqEE

Если вы сделаете это таким образом - особенно когда вы не перезагружаете всю таблицу - iOS сделает намного меньше работы и сделает более качественную анимацию по умолчанию.

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