2015-01-11 17 views
33

私は、Swiftのいくつかのプロパティに対してLazy初期化を使用したいと考えています。 私の現在のコードは次のようになります。Lazy Var vs Let

lazy var fontSize : CGFloat = { 
    if (someCase) { 
    return CGFloat(30) 
    } else { 
    return CGFloat(17) 
    } 
}() 

事はのfontSizeが設定されると、それは決して変わらないということです。不可能である

lazy let fontSize : CGFloat = { 
    if (someCase) { 
    return CGFloat(30) 
    } else { 
    return CGFloat(17) 
    } 
}() 

: は、だから私はこのような何かをやってみたかったです。

はこれだけでは動作します:

let fontSize : CGFloat = { 
    if (someCase) { 
    return CGFloat(30) 
    } else { 
    return CGFloat(17) 
    } 
}() 

だから - 私は遅延ロードされますが、変更することはありませんプロパティをしたいです。 これを行う正しい方法は何ですか? letを使用して、怠け者のinitについて忘れてしまった?または、私はlazy varを使用して、プロパティの一定の性質について忘れてはいけませんか?

+2

私は同意します - スウィフトは怠け者です。怠惰なvarパターン(値が変更されないことが確実な場合)のもう1つの問題は、オブジェクトを突然変異させることで初めてプロパティを読み取ることです(内部的には変化します - 遅延値が格納されます)外部コードの観点からオブジェクトが変更されていなくても、オブジェクトをvarとして宣言しなければなりません。 –

+1

あなたが得ることができる唯一の 'lazy'は 'sw' 2.1のようなものです(Swift 2.1のように)、フロートの割り当てであれば怠け者は心配しません。特にアクセスがあることが分かっている場合は特にです。 – bshirley

答えて

20

これはXcode 6.3 Beta/Swift 1.2 release notesから最新の経典である:CGFloat初期化子にonal

は、定数は、もはや即時 初期化を必要とする一般化されていませんしましょう。新しい規則では、let定数は、使用前に初期化された(varのように) でなければならず、 しか初期化されていない可能性があります。初期化後に再割り当てまたは変更されません。

これは、のようなパターンができます:以前行われて何の 変異が存在しないにもかかわらず、VARの使用を必要と

let x: SomeThing 
if condition { 
    x = foo() 
} else { 
    x = bar() 
} 

use(x) 

を。 (16181314)

明らかに、あなたはこのことで挫折した唯一の人ではありませんでした。

+0

@iGodric - 私はドキュメントの記述を誤解したと思います。私は私のコメントを削除します。 – rghome

+0

これは、一度だけ遅延ロードを禁止していますか? –

16

スウィフトブックhas the following note

その初期値は、インスタンスの初期化が完了するまで、検索されない場合がありますので、あなたは常に、(varキーワードを持つ)変数として怠惰なプロパティを宣言する必要があります。定数プロパティは、初期化が完了する前に常に値を持たなければならないため、遅延として宣言することはできません。

これは、オブジェクトの初期化が完了する前に、すべての定数格納プロパティが計算されるため、言語を実装するコンテキストで意味があります。 letの意味がlazyと一緒に使用されたときに変更された可能性があるわけではありませんが、完了していないため、varはこの時点でlazyの唯一のオプションのままです。

限りあなたが行くを提示2つの選択肢は、私は効率性に基づいてそれらの間で決めると同じように:

  • プロパティの値にアクセスすることはめったに行われず、先行計算するために高価であるされている場合は、I値は例以上20..30%にアクセスしたり、計算が比較的安価であるされている場合はvar lazy
  • を使用することになり、私はlet

注意を使用します。私はさらにプッシュしてコードを最適化しますコンディション

let fontSize : CGFloat = CGFloat(someCase ? 30 : 17) 
+0

"最後に "return"と "()"? – YogevSitton

+0

@godmoneyはい。 'if'ステートメントが条件式に置き換えられると、ステートメントを使用するために必要な多くの構文が削除されます。もちろん、イニシャライザがより複雑な場合、たとえばループを使用する場合は、構文に戻る必要があります。 – dasblinkenlight

+0

大変ありがとうございます – YogevSitton

6

dasblinkenlightが指摘しているように、遅延プロパティは常にSwiftの変数として宣言する必要があります。しかし、Entityが定義されているソースファイル内からしか変更できないように、プロパティを読み取り専用にすることが可能です。これは、「遅延レイ」の定義に最も近いものです。

private(set) lazy var fontSize: CGFloat = { 
    if someCase { 
     return 30 
    } else { 
     return 17 
    } 
}() 
+0

周囲の型の変数を '許可'することはできません。 – Raphael

関連する問題