Данните ми се променят в UITableViewCell, когато превъртя надолу и се върна

Когато попълвам нови данни в моя tableView Controller, горната ми клетка се презаписва от долната. Нека обясня. Имам едно изображение, което се зарежда асинхронно в последния клетъчен ред, в долната част. Всички останали клетки се зареждат статично с изображение, което е в приложението. Когато превъртя надолу приложението си и покажа долната си клетка, която има различно изображение от другите клетки, и превъртя отново нагоре, виждам, че първото изображение на магазина се е променило на динамичното, заредено в долната клетка. Някой знае ли защо се случва това?

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 относно подготви за повторна употреба функция

От документи на Apple:

Ако UITableViewCell обект може да се използва многократно – тоест има идентификатор за повторно използване – този метод се извиква точно преди обектът да бъде върнат от метода UITableView dequeueReusableCellWithIdentifier:. От съображения за производителност трябва да нулирате само атрибути на клетката, които не са свързани със съдържанието, например състояние алфа, редактиране и селекция. Делегатът на табличния изглед в 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 и за достъп до изображението можете да използвате свойството 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