UILabel исчезает в StackView, когда слишком много контента

У меня есть UIStackView с тремя вложенными представлениями в нем: заголовок (UILabel), тело (UILabel) и изображение сообщения (UIImageView). Это последнее изображение добавляется только тогда, когда у сообщения есть imageURL (это необязательно).

Глядя ниже, вы можете увидеть, что когда я показываю изображение, UILabel каким-то образом исчезает из stackView. Как это исправить?

P.S. Забегая вперед, я хочу удалить imageViews, когда пользователь просматривает сообщения, в которых отсутствуют imageViewURL. Есть какие-нибудь советы о том, как действовать здесь? Еще раз спасибо заранее.

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

Ниже приведен соответствующий код:

class FeedTableViewCell: UITableViewCell {
//MARK: Public properties
var post: Post?{
    didSet{
        guard let post = post else {return}

        // Adding user's name
        let attributedText = NSMutableAttributedString(string: post.author.name + " → " + post.group.name, attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14)])

        // Adding date and user's first name
        let dateFormatter = PostDateFormatter()
        dateFormatter.dateStyle = .long
        dateFormatter.timeStyle = .short
        attributedText.append(NSAttributedString(string: "\n" + dateFormatter.string(from: post.createdAt), attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12), NSAttributedString.Key.foregroundColor: UIColor(r: 155/255, g: 161/255, b: 171/255)]))

        // Increasing Spacing
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = 4
        attributedText.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attributedText.length))

        titleLabel.attributedText = attributedText

        // Setting profile image
        iconImageView.setImage(for: post.author, setContentMode: .scaleAspectFit)

        messageTextView.text = post.content

        setupImageSubviews()
    }
}

//MARK: Private implementation
private let iconImageView = CircleImageView(size: 44)

private let titleLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.font = UIFont.systemFont(ofSize: 14)
    label.textColor = .black
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

private let messageTextView: UILabel = {
    let labelView = UILabel()
    labelView.numberOfLines = 0
    labelView.font = UIFont.systemFont(ofSize: 14)
    labelView.translatesAutoresizingMaskIntoConstraints = false
    return labelView
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupDefaultViews()

}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")

}

var stackView = UIStackView()

func setupDefaultViews(){
    backgroundColor = UIColor.white

    stackView.addArrangedSubview(titleLabel)
    stackView.addArrangedSubview(messageTextView)

    contentView.addSubview(iconImageView)
    contentView.addSubview(stackView)

    iconImageView.anchor(top: contentView.topAnchor, leading: contentView.leadingAnchor, bottom: nil, trailing: nil, padding: .init(top: 0, left: 8, bottom: 0, right: 0), size: CGSize(width: 44, height: 44))

    stackView.anchor(top: contentView.topAnchor, leading: iconImageView.trailingAnchor, bottom: contentView.bottomAnchor, trailing: contentView.trailingAnchor, padding: .init(top: 0, left: 8, bottom: 8, right: 8))
    stackView.axis = .vertical
}

private func setupImageSubviews() {

    guard let imageURL = post?.imageURL else {return} // if no image exists, return, preventing image view from taking extra memory and performance to initialize and calculate constraints

    // initialize here instead of globally, so it doesnt take extra memory holding this when no image exists.
    let messageImageView: UIImageView = {
        let imageView = UIImageView()
        let contentImage = UIImage(systemName: "person.crop.circle.fill")!.withTintColor(.gray).withRenderingMode(.alwaysOriginal)
        imageView.kf.setImage(with: imageURL, placeholder: contentImage)
        imageView.contentMode = .scaleAspectFill
        imageView.layer.masksToBounds = true
        imageView.layer.borderWidth = 1
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()

    stackView.addArrangedSubview(messageImageView)
}}

person Kafka    schedule 26.05.2021    source источник
comment
Используйте View Debugger, чтобы увидеть, что происходит с представлениями.   -  person matt    schedule 26.05.2021
comment
Если вы изменяете размер ячейки после, когда она была отображена, вы должны указать табличному представлению обновить макет. Либо путем перезагрузки строки (строк), либо путем вызова performBatchUpdates().   -  person DonMag    schedule 26.05.2021
comment
Поэтому мне удалось решить проблему, изменив свой подход (используя этот отличный пост: stackoverflow.com/questions/18746929/). Однако у меня все еще есть проблема, когда изображения сжимаются, как показано выше, до тех пор, пока я не начну прокрутку, после чего размер строк изменится в соответствии с содержимым. Могу ли я выполнить BatchUpdates после того, как изображения будут помещены в ячейку?   -  person Kafka    schedule 28.05.2021


Ответы (1)


Чтобы люди знали, как я это исправил, я пытался использовать один шаблон ячейки, который обрабатывал бы два разных типа ячеек. Это ошибка, вместо этого используйте информацию в этой link Использование автоматического макета в UITableView для динамических макетов ячеек и переменной высоты строк для правильного создания двух шаблонов ячеек. Я также обнаружил, что этот код гарантирует, что в ячейках правильно отображаются заголовки:

    // Keeps the title text always showing
override func didMoveToSuperview() {
    super.didMoveToSuperview()
    layoutIfNeeded()
}
person Kafka    schedule 18.06.2021