我需要未知元素的最高约束
I need top constraint of unknow element
我有一个应用程序,它通过单击按钮从服务器下载图像。下载图像后,我创建一个新的 imageView 并将其添加到我的 contentView(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 都在同一个地方,在 View 的顶部。现在有了这个约束代码,我在下载
后遇到了这样的代码问题
2017-07-02 14:50:01.018 ImageFromServerTest[11516:1080948] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSLayoutConstraint for >: A multiplier of 0 or a nil second item together with a location for the first attribute creates an illegal constraint of a location equal to a constant. Location attributes must be specified in pairs.'
我相信你在这里遇到了问题:
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)
无论何时使用滚动视图,都有两条经验法则:-
给scrollView相对于superview的leading,trailing,bottom,top约束,即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)
相对于 scrollView 向 contentView 添加约束
@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)
现在添加关于 contentView 的子视图约束(标签、图像)
例如-您收到了第一张图片,因此我们将在您的函数之外维护一个 UIImageView 数组。
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 个图像视图,您可能需要检查数组的数量并相应地增加 scrollView 的 contentView。你可以使用
self.scrollView.contentSize = CGSize(width, height)
我有一个应用程序,它通过单击按钮从服务器下载图像。下载图像后,我创建一个新的 imageView 并将其添加到我的 contentView(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 都在同一个地方,在 View 的顶部。现在有了这个约束代码,我在下载
后遇到了这样的代码问题2017-07-02 14:50:01.018 ImageFromServerTest[11516:1080948] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSLayoutConstraint for >: A multiplier of 0 or a nil second item together with a location for the first attribute creates an illegal constraint of a location equal to a constant. Location attributes must be specified in pairs.'
我相信你在这里遇到了问题:
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)
无论何时使用滚动视图,都有两条经验法则:-
给scrollView相对于superview的leading,trailing,bottom,top约束,即
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)
相对于 scrollView 向 contentView 添加约束
@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)
现在添加关于 contentView 的子视图约束(标签、图像)
例如-您收到了第一张图片,因此我们将在您的函数之外维护一个 UIImageView 数组。
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 个图像视图,您可能需要检查数组的数量并相应地增加 scrollView 的 contentView。你可以使用
self.scrollView.contentSize = CGSize(width, height)