2017-08-19 6 views
0

通常、私はここでstackoverflowに関する新しい質問をしません。質問の90%は検索で簡単に解決されるからです。しかし、時にはこのようにすることはできません。なぜNSLayoutConstraintはオプション型ですか?

私は動的に私のビューコントローラの配列 var timersArray: [GameTimer?] { get set }に追加する複数のオブジェクトclass GameTimer : UIViewを持っています。 私は、そのオブジェクトの制約を処理するための小さなクラスを実装しました。新しいオブジェクトを追加するたびに、ポートレートモードとランドスケープモードの制約も追加します。

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() 

でこのクラスを使用すると私はXCodeのからのエラー警告がをすることを私に言ってい

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)) 
     ] 

インスタンスにいくつかの値を設定しようとすると、 "オプションの型 'NSLayoutConstraint?'の値「開封されたものではなく、それが参照class NSLayoutConstraint : NSObjectだ考えると、NSLayoutConstraintタイプがここに表示され、オプションの理由を手掛かりを得ることができないので、この(timersArray[0]?.topAnchor.constraint(equalTo: view.topAnchor, constant: view.frame.height/4.5))!

のようにすべての制約をアンラップするために私を示唆しています。 オプションであることを避けることはできますか?私は特定のオブジェクトの制約を無効化、constraintsContainerから、その後明確な制約とtimersArrayから私のGameTimerクラス型のオブジェクトを削除し、私はエラーキャッチアンラップこれを実装している - - 理由

スレッド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は私の特定のケースには、オプションのように見えるのはなぜ?

+0

'timersArray'はオプションです。したがって、あなたは「オプションの連鎖」があります。 –

+0

'NSConstraint'は、配列の要素がnilになったときにアンラッピングを要求し、エラーを引き起こすオプションの型になっているのはなぜですか?私は制約を 'var portraitConstraints:[NSLayoutConstraint]'ではないと宣言しました。[NSLayoutConstraint?] ' –

答えて

2

「nil」であってもよい任意のオプションについての問い合わせ、呼び出しプロパティ、添字およびメソッドのプロセスは、オプションの連鎖として定義されます。任意連鎖戻りは、2つの値 - メソッド、プロパティ、および下付き文字に複数のクエリを一緒にグループ化されているので

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. 

つの鎖の障害は「ゼロ」値にチェーン全体、結果に影響を与えます。

あなたのtimersArrayはオプションですか?

+0

これは正解であり、良い説明です。 (投票されました) –

+0

私の質問の一部にお答えいただきありがとうございます!はい、 'GameTimer? '要素を配列から取り除くと、nilになりますが、ここでNSLayoutConstraintがオプションであると思われ、私のXCode要求がアンラッピングを強制するのはなぜですか?私はオプションの型として宣言していません "? 'var portraitConstraints:[NSLayoutConstraint]' –

+1

ありがとうございます。それは私には明らかではありませんでした。オプションのインスタンスのプロパティを使用するnon-optionalインスタンスを呼び出すと、結果の呼び出しはオプションであり、そのためXCodeはアンラッピングを望んでいます。 –

関連する問題