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

时间:2017-06-29 04:15:06

标签: ios swift

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

这是我的代码

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实例正在添加。可能是因为它们都被添加到具有相同名称的视图层次结构中,因此每个新视图都取代了最后一个... 我认为创建一个课程可以解决这个问题,但现在我无法得到任何东西。

这是更新后的代码......

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 个答案:

答案 0 :(得分:3)

  1. 一个问题是表达式:

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

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

    您希望进行浮点数学运算,在进行除法之前将friends - 1转换为CGFloat

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

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

  4. 第二个代码示例存在一些问题:

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

    • 即使我们修正了上述内容,子视图也会重叠,因为您已将它们定义为某个容器宽度的十分之一,但您要调整centerX倍数。 1 /第50次。

      这样做的净效果是视图会重叠,使得看起来只有一个存在。但我相信如果你使用视图调试器,你会发现它们都在那里。您需要更改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)
            }
    
        } 
    
    }