Swift備忘録


The Swift Programming Languageを見ながらPlayGroundで遊んでましたが、気づいたことについてメモしていこうと思います。

### 小ネタ
PlayGroundでコード書いてる時にコンソールを表示したいときは(printlnの値等を表示させる)、view→Assistant Editor→Show Assistant Editorをクリックする。

* Optional
	* 型宣言に?をつけるとnilを許容できる

```swift
var normalStr: String = nil ← これはコンパイル時にエラーになる
var optionalStr: String? = nil ← ok
```

```swift
var greeting = "Hello!"
if let name = optionalStr {
	// この場合、optionalStrがnilなので、この中は評価されない
    greeting = "Hello, \(name)"
}

// println(greeting) → Hello!

// optionalStrを任意の文字列に変更するとif-let内が評価され、greetingはHello, 任意の文字列となる
```

* 高階関数とクロージャ

```swift
// 第一引数にIntの配列、第二引数にIntを受け取りBoolを返す関数を受け取る高階関数を定義する
func hasAnyMatchers(list: Int[], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}

/* 普通に書いた場合 */
var nums = [1,3,5,8,9]
func lessThanTen(number: Int) -> Bool {
    return number < 10
}

/* クロージャを渡す */
hasAnyMatchers(nums, {
    (number: Int) -> Bool in
    return number < 10
    })

/* 省略形 */
hasAnyMatchers(nums, {
    /* 型も省略できる */
    number in
    /* returnが省略できる(1行の時) */
    number < 10
    })
```

至極普通！毎回blocksの書き方思い出す作業がなくなりますね！

* プロパティの監視

```swift
class StepCounter {
    var totalSteps: Int = 0 {
    willSet {
// newValueは予約語？ここでtotalStepsを参照すると、変更前の値が取得できる
        println("About to set totalSteps to \(newValue)")
    }
    didSet {
// oldValueは予約語？変更前後の値が取得できる
        if totalSteps > oldValue  {
            println("Added \(totalSteps - oldValue) steps")
        }
    }
    }
}
```

ば、バリデーションとかに使うのかしら・・・？

* 構造体に固有の値

```swift
/* クラス変数 */
struct SomeStructure {
    static var storedTypeProperty = "some value"
}

var some1 = SomeStructure()
// もちろんそんなプロパティは存在しない
// some1.storedTypeProperty
SomeStructure.storedTypeProperty → some value
```

* クラス変数

```swift
/* クラスの場合はclassを付ける */
class SomeClass {
    class var someValue: Int {
        return 10
    }
}
SomeClass.someValue
```

一瞬インナークラスかと・・・

* mutating修飾子

```swift
struct Point {
    var x = 0.0, y = 0.0
    /* mutatingを外すとx,yに対して操作できない！ */
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}

/* 構造体のパラメータをメソッドで変更する際はmutatingをつける・・・？ */
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveByX(2.0, y:3.0)

/* こんな書き方もできる！？ */
struct Point2 {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        self = Point2(x: x + deltaX, y: y + deltaY)
    }
}

var somePoint2 = Point2(x: 1.0, y: 1.0)
somePoint2.moveByX(2.0, y: 3.0)
somePoint2


/* enumでもやれる！便利！ */
enum TriStateSwitch {
    case Off, Low, High
    mutating func next() {
        switch self {
        case Off:
            self = .Low
        case Low:
            self = .High
        case High:
            self = .Off
        }
    }
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
```

* subscript

```swift
/* subscript 便利なアクセッサ？ */
struct Adder {
    subscript(x: Int, y: Int) -> Int{
        get {
            return x + y
        }
    }
}
Adder()[1,2]
```

* convenience init

```swift
//convenience init!!
class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}
//call convenience initializer
var food = Food()
//call normal initializer
var food2 = Food(name: "hoge")
```

* singleton

```swift
/* dispatch_onec_tが使えるっぽい */
var token: dispatch_once_t = 0
var food3: Food? = nil
dispatch_once(&token, {food3 = Food(name: "food")})
food3
```

dispatch_once_t使わなくてもやれそう