ios - 以编程方式创建一个对象数组 swift 3

标签 ios swift

我想创建一个水平级联的对象数组,我试图创建一个函数来减小代码的大小,但是,似乎创建的对象之间可能存在 NSLayoutConstraint 冲突?

这是我的代码

private func createProfileImageContainers(numberOfFriends: Int) {

    for friends in 1...numberOfFriends {

    let imageViewContainer = UIView()
    imageViewContainer.translatesAutoresizingMaskIntoConstraints = false
    imageViewContainer.backgroundColor = UIColor.blue
    imageViewContainer.frame = CGRect(x: 0, y: 0, width: frame.width / 10, height: frame.width / 10)

        NSLayoutConstraint(item: imageViewContainer, attribute: .centerX, relatedBy: .equal, toItem: container, attribute: .centerX, multiplier: CGFloat((1 / 2) + ((friends - 1) / 50 )), constant: 0).isActive = true

        NSLayoutConstraint(item: imageViewContainer, attribute: .centerY, relatedBy: .equal, toItem: container, attribute: .centerY, multiplier: 1, constant: 0).isActive = true

        addSubview(imageViewContainer)
    }

}

这是调试器的意思

0 的乘数或零第二项与第一个属性的位置一起创建一个等于常量的位置的非法约束。位置属性必须成对指定。'

有什么建议吗?

编辑:

感谢 Robs 的回答,我能够使用调试器解决问题,但是只添加了一个 imageViewContainer 实例。可能是因为它们都被添加到具有相同名称的 View 层次结构中,所以每个新 View 都取代了最后一个...... 我以为创建一个类可以解决这个问题,但现在我无法显示任何内容。

这是更新后的代码...

class profileImageContainer: UIView {

    let imageViewContainer: UIView = {
    let iv = UIView()
    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.backgroundColor = UIColor.blue


    return iv
}()

}


private func createProfileImageContainers(numberOfFriends: Int) {



    for friends in 1...numberOfFriends {


        print(friends)


        let imageViewContainer = profileImageContainer()


        addSubview(imageViewContainer)

        NSLayoutConstraint(item: imageViewContainer, attribute: .width, relatedBy: .equal, toItem: container, attribute: .width, multiplier: 0.1, constant: 0).isActive = true
        NSLayoutConstraint(item: imageViewContainer, attribute: .height, relatedBy: .equal, toItem: container, attribute: .width, multiplier: 0.1, constant: 0).isActive = true

        NSLayoutConstraint(item: imageViewContainer, attribute: .centerX, relatedBy: .equal, toItem: container, attribute: .centerX, multiplier: 0.5 + (CGFloat(friends - 1) / 50.0), constant: 0).isActive = true


        NSLayoutConstraint(item: imageViewContainer, attribute: .centerY, relatedBy: .equal, toItem: container, attribute: .centerY, multiplier: 1, constant: 0).isActive = true



    }


} 

最佳答案

  1. 一个问题是表达式:

    CGFloat((1 / 2) + ((friends - 1) / 50))
    

    那是进行整数除法,然后将得到的整数转换为 CGFloat。实际上,对于前 50 个 friends 值,您的表达式将返回 0

    您想进行浮点运算,在除法之前将 friends - 1 转换为 CGFloat:

    0.5 + CGFloat(friends - 1) / 50.0
    
  2. 我还建议您在添加约束之前添加 subview 。

  3. 您应该指定宽度和高度约束并消除frame 的设置。 frame 将在应用约束时被丢弃,并且在没有宽度和高度约束的情况下,约束是不明确的。


您的第二个代码示例有几个问题:

  • 您的 ProfileImageContainer 有一个 imageViewContainer,但您从未对它做任何事情。所以,您不会看到您的 ProfileImageContainers(因为您没有设置它自己的 backgroundColor)。我可以想象,您最终可能会使用 ProfileImageContainerimageViewContainer 属性做一些有意义的事情(例如,将其添加到 View 层次结构、设置图像等)。但现在,我建议您删除它,因为它只会混淆情况。

  • 即使我们修复了上述问题, subview 也会重叠,因为您已将它们定义为某些容器宽度的 1/10,但您正在调整 centerX 乘以 1/50。

    这样做的最终效果是 View 会重叠,看起来只有一个存在。但我相信如果你使用 View 调试器,你会发现它们都在那里。您需要更改 centerX 约束以使它们不重叠。

无论如何,这是解决上述问题的演绎版:

//  SampleView.swift

import UIKit

class ProfileImageContainer: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)

        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        configure()
    }

    func configure() {
        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = .blue
    }

}

class SampleView: UIView {

    var container: UIView!

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)

        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        configure()
    }

    func configure()  {
        container = UIView()
        container.translatesAutoresizingMaskIntoConstraints = false
        addSubview(container)
        NSLayoutConstraint.activate([
            container.leftAnchor.constraint(equalTo: leftAnchor),
            container.rightAnchor.constraint(equalTo: rightAnchor),
            container.topAnchor.constraint(equalTo: topAnchor),
            container.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])

        createProfileImageContainers(numberOfFriends: 5)
    }

    var friends = [UIView]()

    private func createProfileImageContainers(numberOfFriends: Int) {

        // remove old friends in case you called this before

        friends.forEach { $0.removeFromSuperview() }
        friends.removeAll()

        // now add friends 

        for friend in 0 ..< numberOfFriends {     // easier to go from 0 to numberOfFriends-1 than subtract one later

            print(friend)

            let imageViewContainer = ProfileImageContainer()

            container.addSubview(imageViewContainer)

            NSLayoutConstraint.activate([
                imageViewContainer.widthAnchor.constraint(equalTo: container.widthAnchor, multiplier: 0.1),
                imageViewContainer.heightAnchor.constraint(equalTo: container.heightAnchor, multiplier: 0.1),
                NSLayoutConstraint(item: imageViewContainer, attribute: .centerX, relatedBy: .equal, toItem: container, attribute: .centerX, multiplier: 2 * CGFloat(friend + 1) / CGFloat(numberOfFriends + 1), constant: 0),
                imageViewContainer.centerYAnchor.constraint(equalTo: container.centerYAnchor)
            ])

            friends.append(imageViewContainer)
        }

    } 

}

关于ios - 以编程方式创建一个对象数组 swift 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44816254/

相关文章:

ios - 在自定义 UIVIew 中将 subview 置于最前面

ios - 当用户输入逗号而不是点时我的应用程序崩溃了?

ios - 如何将 UIAppearance 代理属性应用于 UILabel?

ios - UILongPressGestureRecognizer 访问被点击的按钮

ios - 如何以编程方式检测 iPhone 6 & 6 Plus 查看模式

ios - 是否可以在正常状态下在 TableView 中创建可移动行? (见附图)

Swift:比较字符串的第一个字符

macos - 如何检测弹出窗口是否已完成?

iphone - 展开和折叠动画在 ios6 中不起作用

ios - 使用长按手势与 AVFoundation 开始停止录制