The Swift Programming Languageを見ながらPlayGroundで遊んでましたが、気づいたことについてメモしていこうと思います。
小ネタ
PlayGroundでコード書いてる時にコンソールを表示したいときは(printlnの値等を表示させる)、view→Assistant Editor→Show Assistant Editorをクリックする。
- Optional
- 型宣言に?をつけるとnilを許容できる
var normalStr: String = nil ← これはコンパイル時にエラーになる
var optionalStr: String? = nil ← ok
var greeting = "Hello!"
if let name = optionalStr {
// この場合、optionalStrがnilなので、この中は評価されない
greeting = "Hello, \(name)"
}
// println(greeting) → Hello!
// optionalStrを任意の文字列に変更するとif-let内が評価され、greetingはHello, 任意の文字列となる
- 高階関数とクロージャ
// 第一引数に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の書き方思い出す作業がなくなりますね!
- プロパティの監視
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")
}
}
}
}
ば、バリデーションとかに使うのかしら・・・?
- 構造体に固有の値
/* クラス変数 */
struct SomeStructure {
static var storedTypeProperty = "some value"
}
var some1 = SomeStructure()
// もちろんそんなプロパティは存在しない
// some1.storedTypeProperty
SomeStructure.storedTypeProperty → some value
- クラス変数
/* クラスの場合はclassを付ける */
class SomeClass {
class var someValue: Int {
return 10
}
}
SomeClass.someValue
一瞬インナークラスかと・・・
- mutating修飾子
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
/* subscript 便利なアクセッサ? */
struct Adder {
subscript(x: Int, y: Int) -> Int{
get {
return x + y
}
}
}
Adder()[1,2]
- convenience init
//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
/* dispatch_onec_tが使えるっぽい */
var token: dispatch_once_t = 0
var food3: Food? = nil
dispatch_once(&token, {food3 = Food(name: "food")})
food3
dispatch_once_t使わなくてもやれそう