Не удается сбросить UILabel attribuText, когда UITableViewCell используется повторно - PullRequest
3 голосов
/ 30 октября 2019

Проблема

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

Example of my UITableViewCells

Проблема возникает, когда эта конкретная ячейка используется повторно. Украшение зачеркивания все еще там, даже после сброса свойства text и attributedText метки.

Ниже я добавил соответствующие части своего кода:

Представление таблицы

class TimelineViewController: UIViewController {

    private lazy var tableView: UITableView = {
        let tableView = UITableView.init(frame: view.frame, style: .plain)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.register(TimelineTableViewCell.self, forCellReuseIdentifier: TimelineTableViewCell.reuseIdentifier)
        tableView.dataSource = self
        tableView.delegate = self
        return tableView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        addTableViewOnView()
        getTimeline()
    }

}

extension TimelineViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: TimelineTableViewCell.reuseIdentifier,
                                                       for: indexPath) as? TimelineTableViewCell else { fatalError() }
        cell.transactionData = viewModel.timeline[indexPath.row]
        return cell
    }

}

Ячейка табличного представления

class TimelineTableViewCell: UITableViewCell {

    static let reuseIdentifier = "TimelineTableViewCell"

    var transactionData: TimelineResponseModel! {
        didSet {
            // Reset the labels
            transactionDescriptionLabel.text = nil
            transactionDescriptionLabel.attributedText = nil
            transactionValueLabel.text = nil
            transactionValueLabel.attributedText = nil

            // Fill in the values
            transactionDescriptionLabel.text = transactionData.description
            transactionValueLabel.text = Formatter.currency.string(for: transactionData.balance)

            if transactionData.isChargeback {
                let value = Formatter.currency.string(for: transactionData.balance) ?? ""
                transactionDescriptionLabel.attributedText = transactionData.description.strikedThrough()
                transactionValueLabel.attributedText = value.strikedThrough()
            }
        }
    }

    private lazy var transactionDescriptionLabel: UILabel = {
        let transactionDescriptionLabel = UILabel()
        transactionDescriptionLabel.translatesAutoresizingMaskIntoConstraints = false
        transactionDescriptionLabel.font = UIFont.preferredFont(forTextStyle: .footnote)
        transactionDescriptionLabel.adjustsFontForContentSizeCategory = true
        transactionDescriptionLabel.textColor = UIColor.activeText()
        transactionDescriptionLabel.numberOfLines = 0
        return transactionDescriptionLabel
    }()

    private lazy var transactionValueLabel: UILabel = {
        let transactionValueLabel = UILabel()
        transactionValueLabel.translatesAutoresizingMaskIntoConstraints = false
        transactionValueLabel.font = UIFont.preferredFont(forTextStyle: .caption1).bold()
        transactionValueLabel.adjustsFontForContentSizeCategory = true
        transactionValueLabel.textColor = UIColor.activeText()
        return transactionValueLabel
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        addTransactionDescriptionLabel()
        addTransactionValueLabel()
    }

}

Стиль зачеркивания

extension String {

    func strikedThrough() -> NSAttributedString {
        let strikethroughStyle = [NSAttributedString.Key.strikethroughStyle: NSUnderlineStyle.single.rawValue]
        return NSAttributedString(string: self, attributes: strikethroughStyle)
    }

}

Что я пробовал

Я пробовал несколько подходов, безуспех:

  • Переопределить prepareForReuse и сбросить text и attributedText метки там.
  • Создать else после if transactionData.isChargeback, чтобы установить transactionDescriptionLabel и transactionValueLabel атрибутированный текст без декорации

Итак, когда ячейка используется повторно, как я могу сбросить ее метки, чтобы удалить стиль зачеркивания, который я добавил ранее?

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

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

По какой-то причине, если я сбрасываю только attributedText, это работает:

transactionDescriptionLabel.attributedText = nil
transactionValueLabel.attributedText = nil

Или, если я сбрасываюattributedText сначала, а затем сбросьте text, он также работает:

transactionDescriptionLabel.attributedText = nil
transactionValueLabel.attributedText = nil
transactionDescriptionLabel.text = nil
transactionValueLabel.text = nil

Согласно документации UILabel, присвоение нового значения одному свойству заменяет значение другого, поэтомупорядок не должен иметь значения. Но, очевидно, это так.

https://developer.apple.com/documentation/uikit/uilabel/1620538-text

https://developer.apple.com/documentation/uikit/uilabel/1620542-attributedtext

0 голосов
/ 30 октября 2019

Вы должны попытаться установить здесь .attributedText вместо использования `.text '. Если это не сработает, я удалю свой ответ.

// Fill in the values
transactionDescriptionLabel.text = transactionData.description
transactionValueLabel.text = Formatter.currency.string(for: transactionData.balance)

Итак, попробуйте это

transactionDescriptionLabel.attributedText = //
transactionValueLabel.attributedText = //

Еще одна вещь. На самом деле я не люблю didSet. Я предлагаю вам создать метод для настройки вашей ячейки. Вот пример того, что я хочу вам сказать.

func configure(with transactionData: TimelineResponseModel) {
   // Reset the labels
   transactionDescriptionLabel.text = nil
   transactionDescriptionLabel.attributedText = nil
   transactionValueLabel.text = nil
   transactionValueLabel.attributedText = nil

   // Fill in the values
   transactionDescriptionLabel.text = transactionData.description
   transactionValueLabel.text = Formatter.currency.string(for: transactionData.balance)

   if transactionData.isChargeback {
      let value = Formatter.currency.string(for: transactionData.balance) ?? ""
      transactionDescriptionLabel.attributedText = transactionData.description.strikedThrough()
      transactionValueLabel.attributedText = value.strikedThrough()
   }
}

Далее.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: TimelineTableViewCell.reuseIdentifier,
                                                   for: indexPath) as? TimelineTableViewCell else { fatalError() }
    // Thats what I really like
    cell.configure(with: viewModel.timeline[indexPath.row])
    return cell
}
...