Проблема дублирования ячейки Uitable View Swift

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

Мой код ниже:

var cell:chatBubble? = tableView.dequeueReusableCell(withIdentifier:"cell1") as? chatBubble

if cell == nil {
                                                   
    tableView.register(UINib.init(nibName: "chatBubble", bundle: nil), forCellReuseIdentifier: "cell1")

    let arrNib:Array = Bundle.main.loadNibNamed("chatBubble",owner: self, options: nil)!
    cell = arrNib.first as? chatBubble
}
let green = UIColor(red: 179/255, green: 52/255, blue: 199/255, alpha: 1)

if (arrCell.contains(indexPath.row)) {
    print("Exist")
} else {
    arrCell.append(indexPath.row)
    print("Not exist")
                                               
    cell!.showOutgoingMessage(color: green, text: self.animals[indexPath.row], tag: indexPath.row)
}

UITableviewCell


func showOutgoingMessage(color: UIColor, text: String, tag: Int) {
            
    lblmsg.numberOfLines = 0
    lblmsg.font = UIFont.systemFont(ofSize: 18)
    lblmsg.textColor = .white
    lblmsg.text = text
    lblmsg.tag = tag
                    
    let constraintRect = CGSize(width: 0.66 * self.frame.width,
                                                height: .greatestFiniteMagnitude)
    let boundingBox = text.boundingRect(with: constraintRect,
                      options: .usesLineFragmentOrigin,
                      attributes: [.font: lblmsg.font],
                      context: nil)
    lblmsg.frame.size = CGSize(width: ceil(boundingBox.width),
                               height: ceil(boundingBox.height))
                    
    let bubbleImageSize = CGSize(width: lblmsg.frame.width + 20,
                                 height: lblmsg.frame.height + 20)
                
    outgoingMessageView = UIImageView(frame:
                         CGRect(x: self.lblmsg.frame.origin.x,
                                y: self.lblmsg.frame.origin.y,
                                         width: bubbleImageSize.width,
                                         height: bubbleImageSize.height))
    outgoingMessageView.tag = tag
            
    let bubbleImage = UIImage(named: "incoming-message-bubble")?
                       
                        .resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21, bottom: 17, right: 21),
                                        resizingMode: .stretch)
                        .withRenderingMode(UIImageRenderingMode.alwaysTemplate)
                    
                    outgoingMessageView.image = bubbleImage
                    outgoingMessageView.tintColor = color
            self.addSubview(outgoingMessageView)
    }

Я использовал следующую функцию для решения повторяющихся ячеек, но она очищает как 1-я, так и 8-я ячейка (повторно используемая ячейка). я просто хочу очистить вещи в повторяющейся ячейке.

override func prepareForReuse() {
    super.prepareForReuse()
    self.lblmsg.text = nil
    self.outgoingMessageView.image = nil    
} 
                        
[![cell repeat][1]][1]





  [1]: https://i.stack.imgur.com/FRAi4.png
 

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

AdamPro13 15.12.2020 19:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
204
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

  1. Переместите регистрацию пера за пределы функции cellForRow, например, в viewDidLoad вашего контроллера:
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UINib.init(nibName: "chatBubble", bundle: nil), forCellReuseIdentifier: "cell1")
}
  1. Обновите код dequeueReusableCell из
var cell:chatBubble? = tableView.dequeueReusableCell(withIdentifier:"cell1") as? chatBubble

if cell == nil {
                                                   
    tableView.register(UINib.init(nibName: "chatBubble", bundle: nil), forCellReuseIdentifier: "cell1")

    let arrNib:Array = Bundle.main.loadNibNamed("chatBubble",owner: self, options: nil)!
    cell = arrNib.first as? chatBubble
}

к

let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as! chatBubble 
  1. Не выполняйте повторную инициализацию outgoingMessageView в цикле удаления из очереди
outgoingMessageView = UIImageView(frame:
                         CGRect(x: self.lblmsg.frame.origin.x,
                                y: self.lblmsg.frame.origin.y,
                                         width: bubbleImageSize.width,
                                         height: bubbleImageSize.height))

вместо этого обновить кадр

outgoingMessageView.frame = CGRect(x: self.lblmsg.frame.origin.x,
                                   y: self.lblmsg.frame.origin.y,
                                   width: bubbleImageSize.width,
                                   height: bubbleImageSize.height)
  1. Не добавляйте в иерархию просмотра каждый раз, поэтому удалите строку

self.addSubview(outgoingMessageView)

или добавьте это outgoingMessageView только один раз в override func awakeFromNib() или в override func prepareForReuse() или около того

  1. Убедитесь, что вы НЕ смешиваете автомакет и подходы на основе фреймов. Выберите только один из них

Я добавил исходящий просмотр изображений как ioutlet, изменил часть кода, которая создает проблему с дублированием ячеек. Также я применил ваши предложения. Спасибо, Андрей.

user2702179 17.12.2020 06:18

На самом деле следующий фрагмент кода приводит к дублированию ячеек.

if (arrCell.contains(indexPath.row)) {
    print("Exist")
} else {
    arrCell.append(indexPath.row)
    print("Not exist")
                                               
    cell!.showOutgoingMessage(color: green, text: self.animals[indexPath.row], tag: indexPath.row)
}

Я удалил этот фрагмент кода, и дублирование ячеек исчезло.

Другие вопросы по теме