У меня есть пользовательская ячейка с динамической высотой внутри XIB-файла, которая показывает сообщение с сообщением и изображением. Поскольку изображение будет загружено асинхронно из моего API, соотношение сторон изображения будет отправлено с ресурсом. Внутри метода updateConstraints
будет установлено ограничение соотношения сторон с соответствующим множителем.Динамическая высота для ячеек таблицы с изображениями с асинхронной загрузкой
XIB Файл:
Класс клетки:
//
// PostTableViewCell.swift
// Lome
//
// Created by Tobias Feistmantl on 10/09/15.
// Copyright (c) 2015 Tobias Feistmantl. All rights reserved.
//
import UIKit
import Alamofire
class PostTableViewCell: UITableViewCell {
@IBOutlet weak var userProfileImageView: TFImageView!
@IBOutlet weak var usersNameLabel: UILabel!
@IBOutlet weak var usernameLabel: UILabel!
@IBOutlet weak var userProfileButton: TFCellButton!
@IBOutlet weak var distanceLabel: UILabel!
@IBOutlet weak var messageLabel: UILabel!
@IBOutlet weak var postImageView: UIImageView!
@IBOutlet weak var likeCountLabel: UILabel!
@IBOutlet weak var timestampLabel: UILabel!
@IBOutlet weak var likeButton: UIButton!
@IBOutlet weak var constraintBetweenMessageLabelAndPostImageView: NSLayoutConstraint!
var post: Post! {
didSet {
post.author.profileImage(version: .Thumbnail) { image, _ in
self.userProfileImageView.image = image
}
if let name = post.author.fullName {
usersNameLabel.text = name
usernameLabel.text = post.author.username
} else {
usersNameLabel.text = post.author.username
usernameLabel.hidden = true
}
if let attributedMessage = post.attributedMessage {
messageLabel.attributedText = attributedMessage
messageLabel.hidden = false
constraintBetweenMessageLabelAndPostImageView.constant = 15
} else {
messageLabel.hidden = true
messageLabel.attributedText = nil
constraintBetweenMessageLabelAndPostImageView.constant = 0
}
post.image { image, _ in
if let image = image {
self.postImageView.image = image
self.setNeedsUpdateConstraints()
}
}
timestampLabel.text = "Posted \(post.createdAt.timeAgoSinceNow())"
distanceLabel.text = post.distanceText
likeCountLabel.text = "\(post.likesCount) Likes"
likeButton.setImage(post.likeButtonImage, forState: .Normal)
}
}
override func updateConstraints() {
if let aspectRatio = post.imageAspectRatio {
postImageAspectConstraint = NSLayoutConstraint(item: postImageView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: postImageView, attribute: NSLayoutAttribute.Height, multiplier: CGFloat(aspectRatio), constant: 0)
}
super.updateConstraints()
}
func setupUserProfileButton(indexPath: NSIndexPath, viewController: UIViewController) {
userProfileButton.indexPath = indexPath
userProfileButton.addTarget(viewController, action: "userProfileButtonDidTouch:", forControlEvents: .TouchUpInside)
}
var postImageAspectConstraint: NSLayoutConstraint? {
didSet {
if let oldValue = oldValue {
postImageView.removeConstraint(oldValue)
}
if let postImageAspectConstraint = postImageAspectConstraint {
postImageView.addConstraint(postImageAspectConstraint)
}
}
}
override func prepareForReuse() {
super.prepareForReuse()
postImageAspectConstraint = nil
}
}
cellForRowAtIndexPath
метод:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("postCell", forIndexPath: indexPath) as! PostTableViewCell
cell.post = posts[indexPath.row]
cell.setupUserProfileButton(indexPath, viewController: self)
return cell
}
В приложении начать все работает, как ожидалось, но если Я немного размахиваю, препятствия начинают разрушаться, и аспект изображений не прав больше или некоторые другие странных вещи, как показано ниже:
Ошибка:
2015-09-28 11:58:27.546 Lome[32812:528936] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f8a008bf6f0 V:[Lome.TFImageView:0x7f8a008bf470(35)]>",
"<NSLayoutConstraint:0x7f89f9fbc490 V:|-(15)-[Lome.TFCellButton:0x7f8a0087fde0] (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a00831520 Lome.TFCellButton:0x7f8a0087fde0.top == Lome.TFImageView:0x7f8a008bf470.top>",
"<NSLayoutConstraint:0x7f8a008315c0 Lome.TFCellButton:0x7f8a0087fde0.bottom == Lome.TFImageView:0x7f8a008bf470.bottom>",
"<NSLayoutConstraint:0x7f8a00831750 V:[Lome.TFCellButton:0x7f8a0087fde0]-(18)-[UILabel:0x7f8a008806d0'Water']>",
"<NSLayoutConstraint:0x7f8a00831840 H:|-(0)-[UIImageView:0x7f8a00830910] (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a00831890 H:[UIImageView:0x7f8a00830910]-(0)-| (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a008318e0 V:[UILabel:0x7f8a008806d0'Water']-(15)-[UIImageView:0x7f8a00830910]>",
"<NSLayoutConstraint:0x7f8a00831930 V:[UIImageView:0x7f8a00830910]-(20)-[UILabel:0x7f8a00830b90'0 Likes']>",
"<NSLayoutConstraint:0x7f8a00831980 V:[UILabel:0x7f8a00830b90'0 Likes']-(20)-| (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a00860870 UIImageView:0x7f8a00830910.width == 0.6672*UIImageView:0x7f8a00830910.height>",
"<NSLayoutConstraint:0x7f8a0084e990 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f8a008bf270(611)]>",
"<NSLayoutConstraint:0x7f8a0084f930 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7f8a008bf270(375)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f8a008bf6f0 V:[Lome.TFImageView:0x7f8a008bf470(35)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2015-09-28 11:58:27.547 Lome[32812:528936] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7f89f9fbc490 V:|-(15)-[Lome.TFCellButton:0x7f8a0087fde0] (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a00831520 Lome.TFCellButton:0x7f8a0087fde0.top == Lome.TFImageView:0x7f8a008bf470.top>",
"<NSLayoutConstraint:0x7f8a008315c0 Lome.TFCellButton:0x7f8a0087fde0.bottom == Lome.TFImageView:0x7f8a008bf470.bottom>",
"<NSLayoutConstraint:0x7f8a00831750 V:[Lome.TFCellButton:0x7f8a0087fde0]-(18)-[UILabel:0x7f8a008806d0'Water']>",
"<NSLayoutConstraint:0x7f8a00831840 H:|-(0)-[UIImageView:0x7f8a00830910] (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a00831890 H:[UIImageView:0x7f8a00830910]-(0)-| (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a008318e0 V:[UILabel:0x7f8a008806d0'Water']-(15)-[UIImageView:0x7f8a00830910]>",
"<NSLayoutConstraint:0x7f8a00831930 V:[UIImageView:0x7f8a00830910]-(20)-[UILabel:0x7f8a00830b90'0 Likes']>",
"<NSLayoutConstraint:0x7f8a00831980 V:[UILabel:0x7f8a00830b90'0 Likes']-(20)-| (Names: '|':UITableViewCellContentView:0x7f8a008bf270)>",
"<NSLayoutConstraint:0x7f8a00860870 UIImageView:0x7f8a00830910.width == 0.6672*UIImageView:0x7f8a00830910.height>",
"<NSLayoutConstraint:0x7f8a0084e990 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f8a008bf270(611)]>",
"<NSLayoutConstraint:0x7f8a0084f930 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7f8a008bf270(375)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f8a00860870 UIImageView:0x7f8a00830910.width == 0.6672*UIImageView:0x7f8a00830910.height>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
Я думаю, что это что-то делать с повторным использованием клеток, но и как вы можете увидеть, что ограничение будет удалено в методе prepareForReuse
.
В настоящее время я очень расстроен, потому что я пытаюсь решить эту проблему с нескольких дней и не нашел решения.
Надеюсь, у кого-то есть решение.
Заранее спасибо.
Можете ли вы попытаться установить высоту изображения, а не ширину в 'updateConstraints:'. С первого взгляда это кажется неоднозначной ситуацией, поскольку вы уже привязали «ImageView» с горизонтальными макетами с интервалом 0 и затем пытались изменить ширину по высоте. – Gandalf
Это ограничение отношения к формату, а не ограничение ширины. Высота UIImageView в 0.6672 раза больше ширины. Однако, если я устанавливаю фиксированную высоту в IB и не добавляю это ограничение соотношения сторон, это работает, но у меня всегда одинаковая высота и ложное соотношение сторон, потому что каждое изображение отличается. – Tobias
Я знаю, что вы применили ограничение соотношения сторон. Я думаю, вы неправильно поняли, о чем я говорю. В вашем аспекте ограничения ration, 'first item' является' width'. Это означает, что ограничение будет пытаться внести изменения в 'width' не в' height' этого представления. Поэтому, если вы отмените первый и второй элементы от него и измените соотношение сторон в аргументе множителя, у вас будет такое же ограничение, но с разной высотой в соответствии с соотношением сторон изображения. – Gandalf