Мои данные меняются в UITableViewCell, когда я прокручиваю вниз и возвращаюсь

Когда я заполняю новые данные в своем контроллере tableView, моя верхняя ячейка перезаписывается нижней. Позволь мне объяснить. У меня есть одно изображение, которое загружается асинхронно в последней строке ячеек внизу. Все остальные ячейки загружаются статически с изображением, которое есть в приложении. Когда я прокручиваю свое приложение вниз и отображаю свою нижнюю ячейку, которая имеет изображение, отличное от других ячеек, и снова прокручиваю вверх, я вижу, что первое изображение магазина изменилось на динамическое, загруженное в нижнюю ячейку. Кто-нибудь знает, почему это происходит?

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell : shopsTableViewCell = tableView.dequeueReusableCellWithIdentifier("shopCell", forIndexPath: indexPath) as! shopsTableViewCell

    cell.index = indexPath.row
    let qualityOfServiceClass = QOS_CLASS_BACKGROUND
    let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
    let apiCall = webApi()


        dispatch_async(backgroundQueue, {
            apiCall.downloadPhotoAsync("http://api-ytyg.wbbdev.com/files/shops/\(shops[indexPath.row].id)/\(shops[indexPath.row].featured_img)"){(image: UIImage?) -> Void in
                dispatch_async(dispatch_get_main_queue()){
                    if(image != nil){
                        if (cell.index == indexPath.row){
    //                            shops[indexPath.row].photo = image!
                            cell.shopImg?.image = image
                        }

                    }else{
                        shops[indexPath.row].photo = UIImage.init(named: "No_Image_Available.jpg")!
                    }
                }
            }
        })
    cell.shopName?.text = shops[indexPath.row].name
    cell.shopDescription?.text = shops[indexPath.row].address

    cell.label1?.text = shops[indexPath.row].city + " | " + shops[indexPath.row].distance + "Km"
    cell.becomeFirstResponder()
    return cell
}

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

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

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


person Alfro    schedule 30.06.2016    source источник
comment
покажите свое объявление shopImg и shopName, shopDescription   -  person Akshansh Thakur    schedule 30.06.2016
comment
отредактировано, чтобы добавить пользовательский класс ячеек, где было объявление запрошенных вами свойств   -  person Alfro    schedule 30.06.2016
comment
проверьте мой ответ .. и почему бы вам не использовать библиотеку SDWebImage, она очень эффективна по сравнению со всем этим. он будет быстрее обрабатываться с кешем и всем остальным   -  person Akshansh Thakur    schedule 30.06.2016
comment
Я не знаю эту библиотеку. Хотел бы я знать скорее. Прошло много времени с тех пор, как я расследую и скоро приду к концу.   -  person Alfro    schedule 30.06.2016
comment
Я добавил код с помощью этой библиотеки, проверьте.   -  person Akshansh Thakur    schedule 30.06.2016
comment
извините, но, исследуя и пробуя новые вещи, я обнаружил, что розетка вызывает сбой приложения, и только тогда, когда изображение было загружено с сервера. Я отредактировал свой пост, чтобы показать новые захваты и код   -  person Alfro    schedule 30.06.2016


Ответы (2)


это потому, что ваши ячейки используются повторно:

// this line initialize a cell of type shopsTableViewCell 
//if no cell can be reused, get an already used cell else
let cell : shopsTableViewCell 
                 = tableView.dequeueReusableCellWithIdentifier("shopCell",
                                  forIndexPath: indexPath) as! shopsTableViewCell

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

Чтобы избежать этого, вы должны реализовать prepareForReuse в файле класса ячеек для сброса данных и изображения. документы Apple о функция prepareForReuse

Из документов Apple:

Если объект UITableViewCell допускает повторное использование, то есть он имеет идентификатор повторного использования, этот метод вызывается непосредственно перед тем, как объект будет возвращен из метода dequeueReusableCellWithIdentifier: UITableView. Из соображений производительности следует сбрасывать только те атрибуты ячейки, которые не связаны с содержимым, например альфа-канал, редактирование и состояние выбора. Делегат табличного представления в tableView:cellForRowAtIndexPath: всегда должен сбрасывать все содержимое при повторном использовании ячейки. Если объект ячейки не имеет связанного идентификатора повторного использования, этот метод не вызывается. Если вы переопределяете этот метод, вы должны обязательно вызвать реализацию суперкласса.

 //Example :
 override func prepareForReuse() {
    super.prepareForReuse()
    //Do reset here
    this.shopImg?.image = nil
    this.shopName?.text = ""
    this.shopDescription?.text = ""

}
person LHIOUI    schedule 01.07.2016
comment
Хм.. Где реализовать Не могли бы вы объяснить вкратце? - person Krunal Nagvadia; 16.07.2019
comment
Метод является частью UITableViewCell. Подкласс его там. - person Tilo Delau; 20.11.2020

Я думаю, проблема в том, что пока вы прокручиваете, ваши изображения все еще находятся в процессе загрузки (поэтому у вас есть ноль в этой конкретной строке кода). Так что вы должны ждать его.

Я предполагаю, что у вас есть массив изображений. Если вы этого не сделаете, то вы должны сделать один. Вы должны использовать его так:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return arrayThatcontainsShopImages.count
}

Примечание: каждый раз, когда вы добавляете загруженное изображение в этот массив, вы должны вызывать tableView.reloadData()

Использование SDWebImage может быть намного лучше. Посмотрите на следующий код, используя эту библиотеку, вы просто создаете экземпляр UIImageView. затем, используя эту библиотеку, вы можете загрузить изображение непосредственно в экземпляр изображения, а для доступа к изображению вы можете использовать свойство imageView.image класса UIImageView.

 let imageView = UIImageView()
 imageView.sd_setImageWithURL(someURL, placeholderImage: UIImage())
 self.arrayOfImageViews.append(imageView)
person Akshansh Thakur    schedule 30.06.2016
comment
@GregoryWilsonPullyattu Рад, что это помогло! - person Akshansh Thakur; 20.01.2018