SwiftのいくつかのプロパティにLazy初期化を使用したい。私の現在のコードは次のようになります。
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
を使用して、怠zyなinitを忘れますか?または、lazy var
を使用して、プロパティの定数の性質を忘れる必要がありますか?
これは Xcode 6.3 Beta/Swift 1.2リリースノート :
すぐに初期化する必要がなくなるように定数を一般化しました。新しい規則は、使用する前にlet定数(varなど)を初期化する必要があり、初期化のみが可能であることです。初期化後に再割り当てまたは変更されません。
これにより、次のようなパターンが可能になります。
let x: SomeThing
if condition {
x = foo()
} else {
x = bar()
}
use(x)
以前は、変異が発生していなくても、varの使用が必要でした。 (16181314)
これにイライラしたのはあなただけではなかったようです。
Swift book 次のメモがあります :
インスタンスの初期化が完了するまで初期値は取得されない可能性があるため、遅延プロパティを変数として(varキーワードを使用して)常に宣言する必要があります。定数プロパティは、初期化が完了する前に常に値を持っている必要があるため、遅延として宣言できません。
これは、オブジェクトの初期化が完了する前にすべての定数の保存されたプロパティが計算されるため、言語を実装するコンテキストでは意味があります。 let
と一緒に使用すると、lazy
のセマンティクスが変更された可能性があるという意味ではありませんが、まだ実行されていないため、var
が唯一のオプションです。この時点でlazy
。
あなたが提示した2つの選択肢に関しては、効率に基づいてそれらを選択します:
var lazy
let
を使用します注:コードをさらに最適化して、条件をCGFloat
初期化子にプッシュします。
let fontSize : CGFloat = CGFloat(someCase ? 30 : 17)
Dasblinkenlightが指摘しているように、レイジープロパティは常にSwiftの変数として宣言する必要があります。ただし、プロパティを読み取り専用にすることは可能です。そのため、エンティティが定義されたソースファイル内からのみ変更できます。これは、 "lazy let"を定義するのに最も近い方法です。
private(set) lazy var fontSize: CGFloat = {
if someCase {
return 30
} else {
return 17
}
}()