为什么NSLayoutConstraint是可选类型?

时间:2017-08-19 19:49:34

标签: ios swift constraints nslayoutconstraint

通常我会避免在stackoverflow上提出一个新问题,因为90%的问题可以通过搜索轻松解决。但有时你不能这样做。

我添加了几个对象class GameTimer : UIView 我的视图控制器的var timersArray: [GameTimer?] { get set }动态。 我已经实现了一些小类来处理对象的约束。每次添加新对象时,我都会为纵向和横向模式添加约束。

class ConstraintsContainer {

    var portraitConstraints: [NSLayoutConstraint] = []
    var landscapeConstraints: [NSLayoutConstraint] = []

func setGeneralConstraints(timerView: GameTimer?, timerViewSize: CGFloat) {
    timerView?.translatesAutoresizingMaskIntoConstraints = false
    timerView?.heightAnchor.constraint(equalToConstant: timerViewSize).isActive = true
    timerView?.widthAnchor.constraint(equalToConstant: timerViewSize).isActive = true
    print("General constraints")
}

func getDeviceOrientation() {

        if UIDevice.current.orientation == UIDeviceOrientation.portrait || UIDevice.current.orientation == UIDeviceOrientation.portraitUpsideDown {
            NSLayoutConstraint.activate(portraitConstraints)
        } else {
            NSLayoutConstraint.activate(landscapeConstraints)
        }
    }
}

当我尝试在视图控制器中使用此类时

var constraintsContainer = ConstraintsContainer()

并为实例设置一些值

constraintsContainer.portraitConstraints = [
            timersArray[0]?.topAnchor.constraint(equalTo:    view.topAnchor, constant: view.frame.height/4.5),
            (timersArray[0]?.centerXAnchor.constraint(equalTo: view.centerXAnchor))
        ]

        constraintsContainer.landscapeConstraints = [
            (timersArray[0]?.topAnchor.constraint(equalTo: view.topAnchor, constant: view.frame.height/6.5)),
            (timersArray[0]?.centerXAnchor.constraint(equalTo: view.centerXAnchor))
        ]

我有来自XCode的错误警告告诉我“可选类型'NSLayoutConstraint的值?'没有解开“并建议我打开这样的约束(timersArray[0]?.topAnchor.constraint(equalTo: view.topAnchor, constant: view.frame.height/4.5))!

所以,无法弄清楚为什么NSLayoutConstraint类型在这里显示为可选,考虑它的引用class NSLayoutConstraint : NSObject。 有可能避免它是可选的吗?原因 - 当我停用特定对象的约束时,然后清除constraintsContainer中的约束并从GameTimer中删除timersArray类类型的对象并实现此解包我发现错误 -

  

主题1:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)

 func deactivate() {

    NSLayoutConstraint.deactivate(constraintsContainer.portraitConstraints)
    NSLayoutConstraint.deactivate(constraintsContainer.landscapeConstraints)
    constraintsContainer.portraitConstraints.removeAll()
    constraintsContainer.landscapeConstraints.removeAll()
}

为什么NSLayoutConstraint在我的特定情况下似乎是可选的?

1 个答案:

答案 0 :(得分:2)

在可选的“nil”上查询,调用属性,下标和方法的过程被定义为可选链接。可选链接返回两个值 -

if the optional contains a 'value' then calling its related property, methods and subscripts returns values.

if the optional contains a 'nil' value all its its related property, methods and subscripts returns nil.

由于对方法,属性和下标的多个查询被组合在一起,因此对一个链的失败将影响整个链并导致'nil'值。

你的计时器阵容是可选的吗?