ios - 在自定义 UITableViewCell 中保持 UIImageView 的纵横比

标签 ios swift uitableview

所以我想做的是让我的自定义 UITableViewCell 包含一个里面有图像的 UIImageView,并让这个 ImageView 始终保持与其中的图像具有相同的纵横比,同时具有与单元格相同的宽度。单元格的高度应与 ImageView 的高度相同。

这是我使用的代码:

我的自定义 UITableViewCell 类:

import UIKit

class ImageTableViewCell: UITableViewCell {

    var imageURL: NSURL? {
        didSet {
            fetchImage()
        }
    }

    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

    @IBOutlet weak var myImageView: UIImageView!

    func fetchImage() {
        myImageView?.image = nil

        guard let imageURL = self.imageURL else {
            return
        }
        activityIndicator?.startAnimating()
        let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
        dispatch_async(queue) {
            guard let imageData = NSData(contentsOfURL: imageURL) else { return }
            dispatch_async(dispatch_get_main_queue()) {
                guard imageURL == self.imageURL else { return }
                if let image = UIImage(data: imageData) {
                    self.tweetImage?.image = image
                    self.tweetImage?.sizeToFit()
                } else { self.tweetImage?.image = nil }
                self.spinner?.stopAnimating()
            }
        }
    }

    func addRatioConstraint(ratio: CGFloat) {
        let ratioConstraint = NSLayoutConstraint(item: myImageView, attribute: .Width, relatedBy: .Equal, toItem: myImageView, attribute: .Height, multiplier: ratio, constant: 0)
        ratioConstraint.priority = UILayoutPriorityDefaultHigh //important piece of code
        myImageView?.addConstraint(ratioConstraint)
    }
}

下面是来自 UITableViewController 的相关代码:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.rowHeight = UITableViewAutomaticDimension
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let mention = mentionSections[indexPath.section].mentions[indexPath.row]
    switch mention {
    case .Image(let url, let ratio):
        guard let imageCell = tableView.dequeueReusableCellWithIdentifier(.Image, forIndexPath: indexPath) as? ImageTableViewCell else { fallthrough }
        imageCell.imageURL = url
        imageCell.addRatioConstraint(CGFloat(ratio))
        return imageCell
    //left out code for additional irrelevant cells
    }
}

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    let mention = mentionSections[indexPath.section].mentions[indexPath.row]
    switch mention {
    case .Image(_, _): return 200
    default: return 41
    }
}

并了解我正在使用 dequeueReusableCellWithIdentifier 函数做什么(它只是为我简化事情的一个小扩展):

private extension UITableView {

    enum CellIdentifier: String {
        case Image = "Image"
        case Keyword = "Keyword"
    }

    func dequeueReusableCellWithIdentifier(cellIdentifier: CellIdentifier, forIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        return self.dequeueReusableCellWithIdentifier(cellIdentifier.rawValue, forIndexPath: indexPath)
    }
} 

抱歉有这么多代码,但我觉得我必须包含所有这些。

问题来了!我遇到的问题是,当 View 首次加载时,一切看起来都很棒,但是当我将设备转为横向然后再将其转回纵向时,我失去了宽高比并且图像被压扁了。像这样:

http://i.imgur.com/tcnBfyH.jpg

但是,如果我删除这行代码(在 ImageTableViewCell 类的 addRatioConstraint(ratio: CGFloat) 方法中):

ratioConstraint.priority = UILayoutPriorityDefaultHigh

(这意味着优先级现在是 1000,而不是我认为的 750),一切都按预期工作,除了我现在在控制台中打印出一个错误:

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:0x7fcfd4d3e690 UIImageView:0x7fcfd4e29a70.trailing == UITableViewCellContentView:0x7fcfd4e29900.trailingMargin>",
    "<NSLayoutConstraint:0x7fcfd4d3f5c0 UIImageView:0x7fcfd4e29a70.bottom == UITableViewCellContentView:0x7fcfd4e29900.bottomMargin>",
    "<NSLayoutConstraint:0x7fcfd4d3f610 UIImageView:0x7fcfd4e29a70.top == UITableViewCellContentView:0x7fcfd4e29900.topMargin>",
    "<NSLayoutConstraint:0x7fcfd4d3f660 UIImageView:0x7fcfd4e29a70.leading == UITableViewCellContentView:0x7fcfd4e29900.leadingMargin>",
    "<NSLayoutConstraint:0x7fcfd4d52010 UIImageView:0x7fcfd4e29a70.width == 1.34387*UIImageView:0x7fcfd4e29a70.height>",
    "<NSLayoutConstraint:0x7fcfd4e1f200 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7fcfd4e29900(341)]>",
    "<NSLayoutConstraint:0x7fcfd4e1f250 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcfd4e29900(199.5)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fcfd4d52010 UIImageView:0x7fcfd4e29a70.width == 1.34387*UIImageView:0x7fcfd4e29a70.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.

所以基本上 Xcode 所做的就是打破我的方面约束来尝试修复一些冲突。它有效。在我看来,这应该意味着降低该约束的优先级也应该可以解决问题?

任何帮助将不胜感激,我已经为此苦苦挣扎了好几天。

最佳答案

this answer ,您正在设置可变宽度约束以及尾随和前导约束。这会引起冲突。

用 centerX 约束替换尾随/前导约束。

关于ios - 在自定义 UITableViewCell 中保持 UIImageView 的纵横比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31789761/

相关文章:

iphone - 禁用 UITableview 触摸时显示选择时出现问题?

html - iOS Safari 中设备旋转后页面底部的空白

objective-c - JSONkit 排序问题

swift - 是否可以对导入进行别名?

json - 如何使用 Alamofire 4.0 发出 POST 请求并且参数是文本而不是 json

iphone - OpenGL es View 和 uitableview

iOS 8 建议的应用程序图标锁屏

javascript - Phonegap 等待数据库事务完成

ios - 文本在框架中未正确缩放

ios - 在 swift 3 中重新加载部分方法?