初見殺しのSwiftヘンテコ構文
Void, Emptyって何?
まず、Void。これは空のTuple、戻値無しを意味する。Swiftでは戻値無しを空のTupleで代用するのだ。下記の(1)の部分はClosureを格納する配列を意味する。
(2)の部分は、関数の引数が引数/戻値ペアが()->Void
である事を示す。関数本体部分では受取ったClosureを引数名を使って呼出している。
// 初見殺しのヘンテコ変数初期化, que: 関数格納配列のinitializer呼出し
var que = [()->Void]() // (1)
func enque(ope: @escaping ()->Void) { // (2)
que.append(ope)
}
enque { print("executed") }
enque { print("more exec") }
que.forEach { $0() }
実行すると
executed
more exec
となる。
func foo() {
fatalError("fatal")
print("Never stop")
}
これをコンパイルすると、警告、注意が出る。
warning: will never be executed
print("Never stop")
^
note: a call to a never-returning function
fatalError("fatal")
戻って来ないと注意されるんだけど、それを明示的に示す次のコードを付けても警告、注意は無くならない。@Swift5.1
func foo() -> Never {
fatalError("fatal")
print("Never stop")
}
正直Neverの使いどころがよく解らん。Result<Void, Never>
とかってどこかで見た様な気がする。
引数付きClosureを取る関数の書き方
下記ソースではClosureを定義して呼出している。呼出し時には型指定e:Int
は不要。e
で問題無し。
func create(_ handler: (Int) -> Void) {
handler(1) // closureはhandlerという名でアクセス
}
create( {(e:Int) in print(e) } ) // => 1
値付き列挙子を持つenum
名前付きタイプの中でもenumがC言語とは大きく異なっている。下記のコードは型パラメータElement付きのenum Eventを定義して、列挙子nextに1を付与してインスタンス化している。
public enum Event<Element> {
case next(Element)
case error(Error)
case completed
}
let a:Event<Int> = Event.next(1)
print(a) // => next(1)
case文は、次の様に横に書ける
enum Kolor {
case red, blue, green
}
let b = Kolor.red
print(b) // => red
func付きenumを定義して呼び出してみる。
// func付きenum
enum SKolor {
case red, blue, green
func action() {
switch self {
case .red:
print("red")
default:
print("other")
}
}
}
let c = SKolor.blue
c.action() // => next(1)
keyPathリテラル
\.name
とかっていきなりbackslashから始まって何だ?Swift5からkeyPathリテラルって機能が付加されている。要するにプロパティーへのアクセスを記述する方法らしい。
import Foundation
class Person: NSObject {
@objc dynamic var name: String
init(name: String) {
self.name = name
}
}
let person = Person(name: "hoge")
print(person.name)
// KVC
person.setValue("fuga", forKey: #keyPath(Person.name)) // "hoge"
person.value(forKey: #keyPath(Person.name)) // "fuga"
print(person.name)
person[keyPath: \Person.name] = "NG"
print(person.name) // "NG"
person[keyPath: \.name] = "OK"
print(person.name) // "OK"