Posted at

Swiftの変数定義あれこれ

More than 3 years have passed since last update.


はじめに

Swiftの変数定義はいくつかパターンがあって忘れてしまうのでメモ。

基本部分は忘れることは無いのだが、一応書いておく。


基本1

基本的な定義は以下になります。

var value:Int

JavaやRubyなどと同じ普通の定義。

この定義をした場合はinitで値を設定するか、使用するまでに値を設定する必要がある。

class Hoge {

var value:Int

init() {
self.value = 1
}
}

もしくは

var value:Int

if randBool() {
value = 1
} else {
value = 2
}

print("\(value)")

randBoolはランダムにBoolを返すメソッドとする。


基本2

すでに初期値が決まっている場合

var value:Int = 1

あらかじめ値を設定することで初期化ロジックを省くことができる。

Swiftは型推論型を採用しているので、明らかにIntとわかっている場合は以下のようにも書ける。

var value = 1

注意点としてはFloat型の扱いである。

Float型とCGFloatは別の型であり、以下のように定義するとFloat型になるのでCGPointなどを使う場合は注意が必要。

var value = 0.5

CGFloatを使う場合は型を書く必要がある。

var value:CGFloat = 0.5


基本3

定数として値を変えたく無い場合

let value = 1

varletに変えるだけである。

let value = 1

value = 2 // NG!

注意点としては、letはポインタアドレスなどを固定するだけなので以下のようなコードは正常に動作する。

let hoge = Hoge()

hoge.value = 1 // OK!

ArrayDictionaryletで定義すると値を変えれないので、これもまた注意。

let values = [1,2,3]

values.append(4) // NG!


基本4

staticとして定義する場合

他の言語と相違無いので説明は割愛。

static let value = 1


基本5

変数に値は入っているが、初期化のタイミングでは値を入れれない場合

var value:Int

だと、初期化時にデータを入れなければならない。

var value:Int!

その場合は!をつけることで解決する。

主にxibとの繋ぎこみで使ったりする。

@IBOutlet weak var valueView:UIView!


基本6

変数に値が入っているかどうかわからない場合

var value:Int?

このようにすることでOptionalを使用できる。

プログラマーがnilチェックをしないで変数を使ったりできないようになる。

if let value = self.value {

print("\(value)")
}

このような使い方ができる。

flatMapなどで値を取り出したりもできるが、横道にそれるのでここでは割愛。

この辺は結構奥深くて面白いです。

※余談ですが、letの定数では!?を使う事は無いと思います。(一応使えますが・・・無意味なきがする。)


基本7

基本というと結構難しいけれど、オーナーシップを持ちたく無い変数を定義する場合

weak var hoge:Hoge?

このように定義することで強参照を防げます。

weak(弱参照)の使うタイミング(特にクロージャの中)について説明してみるに説明を書いてますので、良ければみてください。

なお、プリミティブ型っぽい型には使えません。(無意味なので)


よく使うけど忘れる定義

ここからが本題。

僕がよく使うけど、忘れる定義の仕方を書きます。

応用というほどでは無いですし、全部を網羅しているわけでもありません。


応用1

変数のsetter/getterを作りたいとき

var value:Int? {

get {
// 1足してデータを返したい。
return self.value + 1
}
set {
// 1引いてデータを設定したい。(setの後に`newValue`の変数名を定義することもできます。僕はそのまま使っちゃいますが。)
self.value = newValue + 1
}
}


応用2

変数のgetterだけ作りたい

var value:Int? {

return self.value
}

簡略化して書けます。


応用3

値が設定された後にフックして別の処理をしたい場合

var value:Int = 1 {

didSet {
// 再描画させるなど...
self.render()
}
}

この他にもいろいろ便利なフック処理があります。

僕はdidSetを多用するので、これだけ紹介します。


応用4

いつも忘れるやつ。

初期値を設定して返したいが、使われない場合は初期化をしたく無い場合

lazy var hoge:Hoge = {

// Hoge()がとても重い処理だったり、インスタンスが作成されてから処理をしたい場合
// この処理は一度しか呼び出されない。
return Hoge()
} ()

=と最後の()がミソ。

self.viewのレンダリングが終わったviewWillAppear以降で使いたい時に便利。

self.frameを使ってViewを作成したいときとか

lazy var hogeView:HogeView = {

let hoge = HogeView(frame: self.freame)
hoge.delegate = self
return hoge
}()

// 上記のように定義していると以下のように使えてコードがスマートになります。
self.view.addChild(self.hogeView)

以上、最後だけよく忘れてしまいます。