我需要未知元素的顶部约束



我有一个应用程序,它通过单击按钮从服务器下载图像。下载图像后,我创建一个新的图像视图并将其添加到我的内容视图(UIView(。我需要创建约束 - 每个新的图像视图都需要来自前一个的顶部约束

func addNewImageToTheScrollView(img: UIImage?) {
if let imageResponse = img {
let imageView = UIImageView(image: imageResponse.crop(rect: CGRect(x: 0, y: imageResponse.size.height/2, width: self.contentView.frame.width, height: 200)))
self.contentView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
let x = NSLayoutConstraint(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: self.contentView, attribute: .centerX, multiplier: 1.0, constant: 0)
let y = NSLayoutConstraint(item: imageView, attribute: .top, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 30)
let width = NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal, toItem: self.contentView, attribute: .width, multiplier: 1.0, constant: 0)
let height = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 150)
self.contentView.addConstraints([x, y])
imageView.addConstraints([width, height])
}
}

如果我注释约束代码,它将正常工作,除非每个新的 imageView 都位于视图顶部的同一位置。现在有了这个约束代码,我在下载后有这样的代码问题

2017-07-02 14:50:01.018 ImageFromServerTest[11516:1080948] *** 由于未捕获的异常"NSInvalidArgumentException"而终止应用程序,原因:"NSLayoutConstraint for>:乘数为 0 或 nil 的第二项以及第一个属性的位置将创建等于常量的位置的非法约束。位置属性必须成对指定。

每当您使用 scrollView 时,都有 2 条经验法则:-

  1. 根据超级视图,为 scrollView 提供前导、尾随、底部和顶部约束,即self.view

    @IbOutlet weak var scrollView: UIScrollView!
    let leading = NSLayoutConstraint(item: scrollView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leadingMargin, multiplier: 1.0, constant: 0)
    let trailing = NSLayoutConstraint(item: scrollView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailingMargin, multiplier: 1.0, constant: 0)
    let top = NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1.0, constant: 0)
    let bottom = NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: 0)
    
  2. 向内容添加约束相对于滚动视图的视图

    @IbOutlet weak var contentView: UIView!
    let leading = NSLayoutConstraint(item: contentView, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leading, multiplier: 1.0, constant: 0)
    let trailing = NSLayoutConstraint(item: contentView, attribute: .trailing, relatedBy: .equal, toItem: scrollView, attribute: .trailing, multiplier: 1.0, constant: 0)
    let top = NSLayoutConstraint(item: contentView, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1.0, constant: 0)
    //increase the constant according to how much long you need the scrollview to be
    let bottom = NSLayoutConstraint(item: contentView, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1.0, constant: 0) 
    

现在添加与内容视图相关的子视图约束(标签、图像(

例如 - 您收到了您的第一张图像,因此我们将在您的函数之外维护一个 UIImageViews 数组。

var imageViews = [UIImageViews]() //declared outside the function

//received an image here
var imageView = UIImageView() // define the frame according to yourself using frame init method
imageView.image = image
if imageViews.isEmpty { // first image view 
//add constraints to first image view
let x = NSLayoutConstraint(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: contentView, attribute: .centerX, multiplier: 1.0, constant: 0)
let y = NSLayoutConstraint(item: imageView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1.0, constant: 30)
let width = NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal, toItem: self.contentView, attribute: .width, multiplier: 1.0, constant: 0)
let height = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 150)
}
else { //second, third, fourth image view... so on
let x = NSLayoutConstraint(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: contentView, attribute: .centerX, multiplier: 1.0, constant: 0)
let y = NSLayoutConstraint(item: imageView, attribute: .top, relatedBy: .equal, toItem: imageViews[imageViews.count - 1], attribute: .bottom, multiplier: 1.0, constant: 30)
let width = NSLayoutConstraint(item: imageView, attribute: .width, relatedBy: .equal, toItem: self.contentView, attribute: .width, multiplier: 1.0, constant: 0)
let height = NSLayoutConstraint(item: imageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 150)
}
imageViews.append(imageView) 
}

希望您现在有一个想法,如何继续解决此问题。如果图像视图超过 4 或 5 个,您可能需要检查数组的计数并相应地增加滚动视图的内容视图。您可以使用self.scrollView.contentSize = CGSize(width, height)

我相信你在这里有一个问题:

let y = NSLayoutConstraint(item: imageView, attribute: .top, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 30)

"toItem"参数应该有一些值。此外,第一个参数应该是imageView.topAnchor。可能它应该看起来像这样:

let y = NSLayoutConstraint(item: imageView.topAnchor, attribute: .top, relatedBy: .equal, toItem: self.contentView.topAnchor, attribute: .notAnAttribute, multiplier: 1.0, constant: 30)

最新更新