为什么 NSLayoutConstraint 是可选类型?
Why NSLayoutConstraint is optional type?
通常我会避免在Whosebug上在这里问一个新问题,因为90%的问题都可以通过搜索轻松解决。但有时你不能这样做。
我有几个对象 class GameTimer : UIView
添加到数组中
var timersArray: [GameTimer?] { get set }
我的视图控制器动态。
我已经实现了一些小的 class 来处理该对象的约束。每次添加新对象时,我也会添加纵向和横向模式的约束。
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)
}
}
}
当我尝试在我的视图控制器中使用这个class时
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 的错误警告,告诉我 "value of optional type 'NSLayoutConstraint?' is not unwrapped" 并建议我像这样解开每个约束 (timersArray[0]?.topAnchor.constraint(equalTo: view.topAnchor, constant: view.frame.height/4.5))!
因此,考虑到它是引用 class NSLayoutConstraint : NSObject
,无法理解为什么 NSLayoutConstraint
类型在这里显示为可选。
是否有可能避免它成为可选的?原因 - 当我停用特定对象的约束,然后从 constraintsContainer
中清除约束并从 timersArray
中删除我的 GameTimer
class 类型的对象并实现此解包时,我发现了一个错误 -
Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
func deactivate() {
NSLayoutConstraint.deactivate(constraintsContainer.portraitConstraints)
NSLayoutConstraint.deactivate(constraintsContainer.landscapeConstraints)
constraintsContainer.portraitConstraints.removeAll()
constraintsContainer.landscapeConstraints.removeAll()
}
为什么 NSLayoutConstraint 在我的特定情况下似乎是可选的?
查询、调用属性、下标和方法的过程可能是 'nil' 被定义为可选链接。可选链接 return 两个值 -
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' 值。
并且您的 timersArray 是可选的?
通常我会避免在Whosebug上在这里问一个新问题,因为90%的问题都可以通过搜索轻松解决。但有时你不能这样做。
我有几个对象 class GameTimer : UIView
添加到数组中
var timersArray: [GameTimer?] { get set }
我的视图控制器动态。
我已经实现了一些小的 class 来处理该对象的约束。每次添加新对象时,我也会添加纵向和横向模式的约束。
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)
}
}
}
当我尝试在我的视图控制器中使用这个class时
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 的错误警告,告诉我 "value of optional type 'NSLayoutConstraint?' is not unwrapped" 并建议我像这样解开每个约束 (timersArray[0]?.topAnchor.constraint(equalTo: view.topAnchor, constant: view.frame.height/4.5))!
因此,考虑到它是引用 class NSLayoutConstraint : NSObject
,无法理解为什么 NSLayoutConstraint
类型在这里显示为可选。
是否有可能避免它成为可选的?原因 - 当我停用特定对象的约束,然后从 constraintsContainer
中清除约束并从 timersArray
中删除我的 GameTimer
class 类型的对象并实现此解包时,我发现了一个错误 -
Thread 1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
func deactivate() {
NSLayoutConstraint.deactivate(constraintsContainer.portraitConstraints)
NSLayoutConstraint.deactivate(constraintsContainer.landscapeConstraints)
constraintsContainer.portraitConstraints.removeAll()
constraintsContainer.landscapeConstraints.removeAll()
}
为什么 NSLayoutConstraint 在我的特定情况下似乎是可选的?
查询、调用属性、下标和方法的过程可能是 'nil' 被定义为可选链接。可选链接 return 两个值 -
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' 值。
并且您的 timersArray 是可选的?