2016-08-25 9 views
2

以下はスイフト3コードがクラッシュします。クラッシュは、明示的なオプションのタイプを削除するか、または強制的にアンラップすることによって簡単に解決できます。view。誰でも説明できますなぜこのコードはクラッシュしますか?なぜUIKitはSwift 3のオプションを好まないのですか?

let view: UIView? = UIView() // note the explicit *optional* type 
_ = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 44.0) 

ノートは:それはスウィフト2.3以下

+2

このコードはクラッシュしません。それはコンパイルされません。 – Rob

+1

Swift 3でこれをやっているのが分かります。最初のパラメータは 'AnyObject'です(' AnyObject'は 'item2'と同じです)。オプションを渡した場合、正しく警告されます。これは 'Any'(' item2'のような 'Any''ではなく)です。コンパイラは、最初のパラメータがオプションであってはならないという事実について、私たちにはっきりと警告していません。しかし、それはオプションではありません、そして、あなたがオプションのものを渡そうとすると、それは明らかに好きではありません。 – Rob

+0

はい、私はSwift 3(Xcode 8)を意味しました。 –

答えて

3

理由は、UIViewUIView?で完全に異なるタイプです。 UIViewObjective-Cクラスであり、UIView?スウィフト列挙であり、これはUIViewを含むことができます。反対にObjective-C nullableではコンパイラのヒントに過ぎません。

+0

私はそれを得ましたが、この理由のためにどうやってクラッシュを止めることができますか? – Steve

+0

@Steve UIKitで使用するには、オプションのラップを解除する必要があります –

4

NSLayoutConstraint(item:, attribute:, relatedBy:, toItem:, attribute:, multiplier:, constant:)でコンパイルされませんAnyとして入力itemパラメータがあります。

public convenience init(item view1: Any, attribute attr1: NSLayoutAttribute, relatedBy relation: NSLayoutRelation, toItem view2: Any?, attribute attr2: NSLayoutAttribute, multiplier: CGFloat, constant c: CGFloat) 

をしかし、クラッシュから、あなたはそれを収集することができますパラメータは実際にはUIViewまたはUILayoutGuideを受け入れることができます:

キャッチされていない例外 'NSInvalidArgumentException'のためアプリを終了します。理由: 'NSLayoutConstraint for Optional(UIView:0x7fa0fbd06650;フレーム=(0 0; 0 0);レイヤー= CALayer:0x60800003bb60):制約はそれぞれUIView、UILayoutGuideのインスタンスでなければなりません。

コンパイラは、コンパイル時にitemの型をチェックできません。何かを受け入れるように定義されています。しかし、私たちがアクセスできない実装の詳細では、このメソッドは、オプションのUIViewまたはUILayoutGuideだけを受け入れます。

だからguardステートメントを追加します。それはクラッシュなぜ

let view: UIView? = UIView() 
guard let view = view else { // Proceed only if unwrapped 
    fatalError() 
} 
let _ = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 0.0, constant: 44.0)