Swiftおさらい

  • 8,599 views
Uploaded on

この資料は発表当時(2014/6/24)のものです。既に仕様が変わっている部分もありますので、ご注意ください。

この資料は発表当時(2014/6/24)のものです。既に仕様が変わっている部分もありますので、ご注意ください。

More in: Travel , Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
8,599
On Slideshare
0
From Embeds
0
Number of Embeds
11

Actions

Shares
Downloads
27
Comments
0
Likes
34

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Swift おさらい LINE Developer Meetup in Fukuoka #5 @taketin 2014/06/24
  • 2. 自己紹介 @taketin LINE Fukuoka iOS developer PHP, Ruby, Objective-C (だいたい)毎週木曜19:30 〜 Fukuoka.swift よろしくお願いします 初めて買ったマック Macintosh Performa LC630
  • 3. Swift とは?
  • 4. https://developer.apple.com/swift/ http://swift-lang.org/main/
  • 5. https://developer.apple.com/swift/ http://swift-lang.org/main/ ◯
  • 6. Swift is “Objective-C without the C” • Swift言語の開発は2010年7月にAppleエンジニアの 個人プロジェクトから始まった • 設計するにあたって影響を受けた言語は Objective-C、 Rust、Haskell、Ruby、Python、C#、 CLU等 via: http://jp.techcrunch.com/2014/06/05/20140604apples-new-programming-language-has-been-in-development-for-nearly-four-years/#Swift
  • 7. 特徴 • モダン クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。 via: http://ja.wikipedia.org/wiki/Swift_(プログラミング言語)
  • 8. 特徴 • モダン クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。 • 安全 静的な型チェック、変数の初期化の強制、数値型のオーバーフローの検査、 自動参照カウント (ARC) によるメモリ管理など。 via: http://ja.wikipedia.org/wiki/Swift_(プログラミング言語)
  • 9. 特徴 • モダン クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。 • 安全 静的な型チェック、変数の初期化の強制、数値型のオーバーフローの検査、 自動参照カウント (ARC) によるメモリ管理など。 • 高速 Objective-C より速い via: http://ja.wikipedia.org/wiki/Swift_(プログラミング言語)
  • 10. 特徴 • モダン クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。 • 安全 静的な型チェック、変数の初期化の強制、数値型のオーバーフローの検査、 自動参照カウント (ARC) によるメモリ管理など。 • 高速 Objective-C より速い • インタラクティブ コンパイラ言語だが、インタプリタとしてスクリプトを実行することも可能。対話実行環境 (REPL) 付属。 コードの実行結果をグラフィカルに確認しながら開発できる “Playgrounds” を実装。 via: http://ja.wikipedia.org/wiki/Swift_(プログラミング言語)
  • 11. では仕様を見ていきましょう
  • 12. 変数 (var) var city: String = “Hakata” 変数、定数
  • 13. 変数 (var) var city: String = “Hakata” 定数 (let) let city: String = “Hakata” city = “Tenjin” // error 変数、定数
  • 14. 変数 (var) var city: String = “Hakata” 定数 (let) let city: String = “Hakata” city = “Tenjin” // error 型推論 var city = “Tenjin” // String 型と推論 変数、定数
  • 15. 変数名は日本語、ユニコード絵文字も 一部使用可。 var 街 = “博多” 変数、定数
  • 16. 暗黙の型変換はしない。 let label = "old" let age = 36 String(age) + label 型変換
  • 17. () で展開 var city = “Hakata” “welcome to (city).” 変数展開
  • 18. () で展開 var city = “Hakata” “welcome to (city).” 式の評価もできる var section = “Ekimae” “welcome to (city + section).” ※ シングルクォートは使えない。 変数展開
  • 19. nil 許容 (型の後ろに ? を付ける) var optional: String = nil // error Optional Value
  • 20. nil 許容 (型の後ろに ? を付ける) var optional: String = nil // error var optional: String? = nil 通常、変数に nil を入れる事はできない。 Optional Value
  • 21. var foo: String? = “bar” // {Some “bar”} “指定された型の値”、もしくは “nil” の2つの要素を持てるように曖昧な形に 「wrap」されている という表現を使う。 Optional Value
  • 22. 「unwrap」する var optional :String? = “foo” // {Some “foo”} var notOptional = optional! // “foo” ImplicitlyUnwrappedOptional
  • 23. 「unwrap」する var optional :String? = “foo” // {Some “foo”} var notOptional = optional! // “foo” 確実に nil では無いと判断できる場合のみ使用する。 値が nil の場合はランタイムエラーが発生する。 (fatal error: Can't unwrap Optional.None) ImplicitlyUnwrappedOptional
  • 24. 特別な評価式 var optional :String? = “foo” if let notOptional = optional { println(“(notOptional) is not nil”) } else { println(“nil”) } optionalのnil判定を行い、代入しつつbool値を返す ImplicitlyUnwrappedOptional
  • 25. ? は enum Optional<T> ! は struct ImplicitlyUnwrappedOptional<T> のシンタックスシュガー ImplicitlyUnwrappedOptional
  • 26. ? は enum Optional<T> ! は struct ImplicitlyUnwrappedOptional<T> のシンタックスシュガー ⌘ + Click で定義を見れるので、中身を 色々見て理解を深めましょう ImplicitlyUnwrappedOptional
  • 27. class Users { class User { var name: String = "taketin" } var user: User? = User() } OptionalChaining
  • 28. class Users { class User { var name: String = "taketin" } var user: User? = User() } OptionalChaining var users: Users? = Users() if let name = users?.user?.name { println(name) // “taketin” } else { println("error!") }
  • 29. class Users { class User { var name: String = "taketin" } var user: User? = nil } OptionalChaining var users: Users? = Users() if let name = users?.user?.name { println(name) } else { println("error!") // error! }
  • 30. var response = (404, "NotFound") Tuple
  • 31. var response = (404, "NotFound") response.0 // 404 response.1 // “NotFound” Tuple
  • 32. var response = (404, "NotFound") response.0 // 404 response.1 // “NotFound” // ラベル response = (status:404, description:”NotFound”) Tuple
  • 33. var response = (404, "NotFound") response.0 // 404 response.1 // “NotFound” // ラベル response = (status:404, description:”NotFound”) response.status // 404 response.description // “NotFound” Tuple
  • 34. true or false Bool値
  • 35. true or false YES or NO は無くなりました Bool値
  • 36. 配列 var a = [1, 2, 3] var b = String[]() var c = Array<String>() var d = Double[](count: 3, repeatedValue: 0.0) // [0.0, 0.0, 0.0] コレクション
  • 37. 配列イテレーション var array = [1, 2, 3] for value in array { println(value) } コレクション
  • 38. 配列のコピー var a = [1, 2, 3] var b = a // [1, 2, 3] (参照渡し) var a[0] = 9 // [9, 2, 3] b // [9, 2, 3] コレクション
  • 39. 配列のコピー var a = [1, 2, 3] var b = a // [1, 2, 3] (参照渡し) a.append(4) // [1, 2, 3, 4] b // [1, 2, 3] コレクション
  • 40. 配列のコピー var a = [1, 2, 3] var b = a // [1, 2, 3] (参照渡し) a.append(4) // [1, 2, 3, 4] (コピー作成) b // [1, 2, 3] 配列長が変わると新しい配列を作る コレクション
  • 41. 配列のコピー var a = [1, 2, 3] var b = a.copy() // 値渡し コレクション
  • 42. 配列のコピー var a = [1, 2, 3] var b = a.copy() // 値渡し または var b = a b.unshare() // 参照を切る コレクション
  • 43. 配列範囲指定 var array = [1, 2, 3] array[0..2] = [1] // [1, 3] array[0...2] = [1] // [1] コレクション
  • 44. 配列範囲指定 var array = [1, 2, 3] array[0..2] = [1] // [1, 3] array[0...2] = [1] // [1] .. は未満 ... は以下(Rubyと逆なので注意) コレクション
  • 45. ディクショナリ var a = Dictionary<Int, String>() var b = [1:”foo”, 2:”bar”] b[1] = nil // [2:”bar”] コレクション
  • 46. ディクショナリ キーの型は hashable で無くてはならない。 String, Int, Double, Bool はデフォルトで hashable (Hashable プロトコル継承) コレクション
  • 47. ディクショナリイテレーション for (key, value) in dictionary {} // キーのみ、値のみ for key in dictionary.keys {} for values in dictionary.values {} コレクション
  • 48. ディクショナリのコピー var a = [1:”a”, 2:”b”] var b = a // 値渡し a[1] = “z” // [1:”z”, 2:”b”] b // [1:”a”, 2:”b”] コレクション
  • 49. if文 if 条件式 { /* Snip */ } else if 条件式 { /* Snip */ } コントロール
  • 50. while文 while 条件式 { /* Snip */ } do { /* Snip */ } while 条件式 コントロール
  • 51. for文 for var index = 0; index < 5; index++ { /* Snip */ } for index in 0..5 { /* Snip */ } コントロール
  • 52. switch文 let foo = "hoge" switch foo { case "bar": println("bar") case "baz", "hoge": println("baz or hoge") default: println("other") } コントロール
  • 53. switch文 基本 break 動作。 fallthrough を指定すると次の case も処理。 コントロール
  • 54. switch文 いろいろなマッチング case 1...3: // Range case (_, 0): // tuple case (let x, 0): // value bindings case let (x, y) where x == y: // where コントロール
  • 55. enum Fukuoka { case Tenjin case Daimyo case Hakata case Nakasu } 列挙型 (Enum)
  • 56. enum Fukuoka { case Tenjin case Daimyo case Hakata case Nakasu } 列挙型 (Enum) var foo = Fukuoka.Tenjin switch foo { case .Tenjin case .Daimyo case .Hakata case .Nakasu }
  • 57. enum Fukuoka { case Tenjin case Daimyo case Hakata case Nakasu } 列挙型 (Enum) var foo = Fukuoka.Tenjin switch foo { case .Tenjin case .Daimyo case .Hakata } switch must be exhaustive, consider adding a default clause
  • 58. enum Rank: Int { case One = 1 case Two, Three, Four } 列挙型 (Enum)
  • 59. enum Rank: Int { case One = 1 case Two, Three, Four } var rank = Rank.Two // (Enum Value) 列挙型 (Enum)
  • 60. enum Rank: Int { case One = 1 case Two, Three, Four } var rank = Rank.Two // (Enum Value) rank.toRaw() // 2 列挙型 (Enum)
  • 61. enum Rank: Int { case One = 1 case Two, Three, Four } var rank = Rank.Two // (Enum Value) rank.toRaw() // 2 Rank.fromRaw(3) // (Enum Value) 列挙型 (Enum)
  • 62. enum Fukuoka: String { case Tenjin = "天神" case Hakata = "博多" } var city = Fukuoka.Hakata 列挙型 (Enum)
  • 63. enum Fukuoka: String { case Tenjin = "天神" case Hakata = "博多" } var city = Fukuoka.Hakata city = .Tenjin // 型が分かっているので省略可能 列挙型 (Enum)
  • 64. enum Fukuoka: String { case Tenjin = "天神" case Hakata = "博多" func toKana() -> String { switch self { case .Tenjin: return "てんじん" case .Hakata: return "はかた" } } } 列挙型 (Enum)
  • 65. enum Fukuoka: String { case Tenjin = "天神" case Hakata = "博多" func toKana() -> String { switch self { case .Tenjin: return "てんじん" case .Hakata: return "はかた" } } } 列挙型 (Enum) var city = Fukuoka.Tenjin // 天神
  • 66. enum Fukuoka: String { case Tenjin = "天神" case Hakata = "博多" func toKana() -> String { switch self { case .Tenjin: return "てんじん" case .Hakata: return "はかた" } } } 列挙型 (Enum) var city = Fukuoka.Tenjin // 天神 city.toKana() // てんじん
  • 67. Associated Values enum APIResponse { case Success(Int, String) case Error(Int, String, NSError) } 列挙型 (Enum)
  • 68. Associated Values enum APIResponse { case Success(Int, String) case Error(Int, String, NSError) } // if success var res = APIResponse.Success(200, “OK”) 列挙型 (Enum)
  • 69. Associated Values enum APIResponse { case Success(Int, String) case Error(Int, String, NSError) } // if success var res = APIResponse.Success(200, “OK”) // if error var res = APIResponse.Error(403, “Access denied”, error) 列挙型 (Enum)
  • 70. Associated Values switch res { case let .Success(httpStatus, message): … // 成功時処理 case let .Error(httpStatus, message, error): … // エラー処理 } 列挙型 (Enum)
  • 71. Associated Values switch res { case let .Success(httpStatus, message): … // 成功時処理 case let .Error(httpStatus, message, error): … // エラー処理 } a.k.a discriminated unions, tagged unions, or variants. 列挙型 (Enum)
  • 72. func foo(bar: String, baz: Int) -> String {} 関数
  • 73. func foo(bar: String, baz: Int) -> String {} // キーワード指定可 func foo(aaa bar: String, bbb baz: Int) -> String {} 関数
  • 74. func foo(bar: String, baz: Int) -> String {} // キーワード指定可 func foo(aaa bar: String, bbb baz: Int) -> String {} // 引数のデフォルト値指定可 func foo(bar: String, baz: Int = 1) -> String {} 関数
  • 75. // 引数の可変長指定可 (Variadic Parameter) func foo(bar: String, baz: Int...) -> String {} 関数
  • 76. // 引数の可変長指定可 (Variadic Parameter) func foo(bar: String, baz: Int...) -> String {} // 引数の参照渡し (inoutラベル) func swapValue(inout a: Int, inout b: Int) {} swapValue(&a, &b) 関数
  • 77. ネスト func foo() -> Int { func bar() { func baz() { } baz() } bar() } foo() 関数
  • 78. 返り値が関数 func foo() -> ((Int, Int) -> String) { func bar(number: Int, number2: Int) -> String { return String(number + number2) } return bar } var bar = foo() bar(1,2) 関数
  • 79. 返り値がタプル func getTuple() -> (Double, Int, String) { return (1.0, 2, "3") } var result = getTuple() result.0 // 1.0 result.1 // 2 result.2 // "3" 関数
  • 80. 基本形 sort([“A”, “C”, “B”], { (s1: String, s2: String) -> Bool in return s1 < s2 }) // [“A”, “B”, “C”] クロージャ
  • 81. 型推論が効く sort([“A”, “C”, “B”], { (s1: String, s2: String) -> Bool in return s1 < s2 }) ▼ sort([“A”, “C”, “B”], { s1, s2 in return s1 < s2 }) クロージャ
  • 82. 式が1つだけの場合 return が省略できる sort([“A”, “C”, “B”], { s1, s2 in return s1 < s2 }) ▼ sort([“A”, “C”, “B”], { s1, s2 in s1 < s2 }) クロージャ
  • 83. 引数をプレースホルダで置換できる sort([“A”, “C”, “B”], { s1, s2 in s1 < s2 }) ▼ sort([“A”, “C”, “B”], { $0 < $1 }) クロージャ
  • 84. Operator Functions を使用する sort([“A”, “C”, “B”], { $0 < $1 }) ▼ sort([“A”, “C”, “B”], < ) クロージャ
  • 85. Operator Functions を使用する sort([“A”, “C”, “B”], { $0 < $1 }) ▼ sort([“A”, “C”, “B”], < ) 式によってはここまで簡略化できる クロージャ
  • 86. Trailing Closures sort([“A”, “C”, “B”], { $0 < $1 }) ▼ sort([“A”, “C”, “B”]) { $0 < $1 } クロージャ
  • 87. Trailing Closures sort([“A”, “C”, “B”], { $0 < $1 }) ▼ sort([“A”, “C”, “B”]) { $0 < $1 } 引数の最後がクロージャの場合、外出し記述可 クロージャ
  • 88. Trailing Closures sort([“A”, “C”, “B”], { $0 < $1 }) ▼ sort([“A”, “C”, “B”]) { $0 < $1 } 引数の最後がクロージャの場合、外出し記述可 sort([“A”, “C”, “B”]) { < } ※これはエラーになった クロージャ
  • 89. blocks 内で self を使った場合の循環参照回避 // lang: Objective-C __weak BlockOwner *weakSelf = self; _block = ^() { NSLog(@"name: %@", weakSelf.name); }; クロージャ
  • 90. blocks 内で self を使った場合の循環参照回避 // lang: Swift self.aProperty = { [unowned self] in // closure capture list self.doSomething() } クロージャ
  • 91. blocks 内で self を使った場合の循環参照回避 // lang: Swift self.aProperty = { [unowned self] in // closure capture list self.doSomething() } 引き続き注意が必要 >< クロージャ
  • 92. class Foo { var bar: String init(baz: Int) { // コンストラクタ self.bar = baz // propertyイニシャライズ必須 } func hoge(fuga: Int, piyo: Int) {} deinit {} // デストラクタ } クラス
  • 93. コンストラクタ init() がコンストラクタ 引数がある場合 init(baz: Int) はインスタンス生成時に引数ラ ベルを指定する必要あり var foo = Foo(baz: 1) クラス
  • 94. コンストラクタ init() がコンストラクタ 引数がある場合 init(baz: Int) はインスタンス生成時に引数ラ ベルを指定する必要あり var foo = Foo(baz: 1) ただし、_ をラベルにする事で回避できる init(_ bar:Int) // var foo = Foo(1) クラス
  • 95. コンビニエンスコンストラクタ class Foo { var bar:Int init(baz: Int) { self.bar = baz } func hoge(fuga:Int, piyo:Int) {} convenience init() { self.init(baz:0) } } クラス
  • 96. コンビニエンスコンストラクタ var foo = Foo() foo.bar // 0 コンストラクタ引数を省略する事ができる。その場合 convenience init 内に書かれた値で初期化される。 クラス
  • 97. 継承 class Foo : Bar { } クラス
  • 98. 継承 class Foo { } Objective-C と違い、基底クラスが無い場合は 継承を省略できる クラス
  • 99. メソッドオーバーライド class Foo : Bar { override func baz() { } } クラス
  • 100. メソッドオーバーライド class Foo : Bar { override func baz() { } } スーパークラスと同名のメソッドを定義していても、 override が無ければ別メソッドとして認識される クラス
  • 101. コピー var foo1 = FooClass() foo1.bar // 10 var foo2 = foo1 foo2.bar // 10 クラス
  • 102. コピー var foo1 = FooClass() foo1.bar // 10 var foo2 = foo1 foo2.bar // 10 foo1.bar = 50 foo2.bar // 50 クラス
  • 103. コピー var foo1 = FooClass() foo1.bar // 10 var foo2 = foo1 // クラスは参照渡し foo2.bar // 10 foo1.bar = 50 foo2.bar // 50 クラス
  • 104. コピー 値渡しでコピーしたい場合は、 import Foundation して NSCopying を継承。 copyWithZone() メソッドを自前で実装する。 (Objective-C と同じイメージ) via: http://qiita.com/taketin@github/items/abcd2bea9e5888afa141 クラス
  • 105. 比較 (===) var foo1 = FooClass() var foo2 = FooClass() foo1 === foo2 // false クラス
  • 106. 比較 (===) var foo1 = FooClass() var foo2 = FooClass() foo1 === foo2 // false var foo3 = foo1 foo3 === foo1 // true クラス
  • 107. 比較 (===) var foo1 = FooClass() var foo2 = FooClass() foo1 === foo2 // false var foo3 = foo1 foo3 === foo1 // true インスタンスのアドレス比較を行う クラス
  • 108. Getter, Setter class Foo { var bar: Int { get { return 10 } set { self.baz = newValue } } var baz: Int = 0 } クラス - プロパティ
  • 109. Getter, Setter class Foo { var bar: Int { get { return 10 } set { self.baz = newValue } } var baz: Int = 0 } setter は “newValue” で新しい値を参照できる クラス - プロパティ
  • 110. Getter, Setter class Foo { var bar: Int { get { return 10 } } var baz: Int = 0 } get のみ書く事で ReadOnly として定義できる クラス - プロパティ
  • 111. willSet, didSet class Foo { var bar:Int { willSet {} didSet {} } } Objective-C の KVO のような動きができる クラス - プロパティ
  • 112. 遅延ロード class Foo { @lazy var bar = SomeClass() } var foo = Foo() // ここでは bar 未初期化 foo.bar // ここで bar 初期化 クラス - プロパティ
  • 113. Type Property Syntax class Foo { class var bar:Int { return 1 } } Foo.bar // 1 クラス - プロパティ
  • 114. class Foo { var bar:Int = 5 init() {} subscript(index: Int) -> Int { return self.bar * index } } Subscript
  • 115. class Foo { var bar:Int = 5 init() {} subscript(index: Int) -> Int { return self.bar * index } } var foo = Foo(); foo[10] // 50 オブジェクトへの添字アクセスができる Subscript
  • 116. class Foo { var bar:Int = 5 init() {} subscript(index: Int) -> Int { get { /* Snip */ } set { /* Snip */ } } } アクセスコントロールも可能 Subscript
  • 117. イニシャライズ struct Foo { var bar: Int = 1 func baz() -> String { return "test" } } var foo = Foo() 構造体 (Structure)
  • 118. イニシャライズ struct Foo { var bar: Int func baz() -> String { return "test" } } var foo = Foo(bar: 1) 構造体 (Structure)
  • 119. mutating struct Foo { var bar: Int = 1 func baz() { bar = 10 // コンパイルエラー } } 構造体 (Structure)
  • 120. mutating struct Foo { var bar: Int = 1 mutating func baz() { bar = 10 } } 構造体 (Structure)
  • 121. static variable struct Foo { static var bar: Int = 1 } Foo.bar // 1 構造体 (Structure)
  • 122. コピー var foo1 = Foo() foo1.bar // 1 var foo2 = foo1 foo1.bar = 10 構造体 (Structure)
  • 123. コピー var foo1 = Foo() foo1.bar // 1 var foo2 = foo1 foo1.bar = 10 foo2.bar // 1 構造体は値渡し(クラスは参照) 構造体 (Structure)
  • 124. protocol FooProtocol { var bar: String { get } func baz() -> String } Protocol
  • 125. protocol FooProtocol { var bar: String { get } func baz() -> String } class FooClass : FooProtocol { var bar: String = “hoge” func baz() -> String { /* Snip */ } } Protocol
  • 126. protocol FooProtocol { var bar: String { get set } // getter, setter 必須 func baz() -> String } class FooClass : FooProtocol { var bar: String { get { /* Snip */ } // set が無いのでコンパイルエラー } Protocol
  • 127. protocol FooProtocol { var bar: String mutating func baz() -> String } struct FooStruct : FooProtocol { var bar: String = “hoge” mutating func baz() -> String { /* Snip */ } } Protocol
  • 128. protocol FooProtocol { } protocol BarProtocol { } class FooClass : FooProtocol, BarProtocol { /* Snip */ } 複数継承も可能 Protocol
  • 129. extension String { func twice() -> String { return "(self) (self)" } } Extention
  • 130. extension String { func twice() -> String { return "(self) (self)" } } var str = “hello” str.twice() // “hello hello” クラスだけでなく型などにも適用できる Extention
  • 131. extension String : FooProtocol { func twice() -> String { return "(self) (self)" } } プロトコルの継承もできる Extention
  • 132. func Foo <任意の型> () {} 型の形式は UpperCamelCase。<HogeType> など。 短く <T> 等が慣習的に使われている。 Generics
  • 133. 型制約無し func repeat<T>(item: T, times: Int) -> T[] { var result = T[]() for i in 0..times { result += item } return result } Generics
  • 134. 型制約無し func repeat<T>(item: T, times: Int) -> T[] { var result = T[]() for i in 0..times { result += item } return result } repeat(“knock”, 4) // [“knock”, “knock”, “knock”, “knock”] Generics
  • 135. 型制約無し func repeat<T>(item: T, times: Int) -> T[] { var result = T[]() for i in 0..times { result += item } return result } repeat(“knock”, 4) // [“knock”, “knock”, “knock”, “knock”] repeat(10, 4) // [10, 10, 10, 10] Generics
  • 136. 型制約有り func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? { for (index, value) in enumerate(array) { if value == valueToFind { return index } } return nil } Generics
  • 137. 型制約有り func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? { for (index, value) in enumerate(array) { if value == valueToFind { return index } } return nil } プロトコル継承の制約を定義できる Generics
  • 138. Any & AnyObject var array : Any[] = ["1", 2, Foo()] TypeCasting
  • 139. Any & AnyObject // 関数型以外なんでも入れる事ができる var array : Any[] = ["1", 2, Foo()] TypeCasting
  • 140. Any & AnyObject // 関数型以外なんでも入れる事ができる var array : Any[] = ["1", 2, Foo()] var array2 : AnyObject[] = [Foo(), Bar(), Baz()] TypeCasting
  • 141. Any & AnyObject // 関数型以外なんでも入れる事ができる var array : Any[] = ["1", 2, Foo()] // クラスのインスタンスのみ入れる事ができる var array2 : AnyObject[] = [Foo(), Bar(), Baz()] TypeCasting
  • 142. 型チェック var array : Any[] = ["1", 2, 3] for obj in array { if obj is Int { println("(obj) is Int") // 2 is Int & 3 is Int } } TypeCasting
  • 143. ダウンキャスト // obj には Base クラスのインスタンスが入っている // Base を継承した Bar クラスが定義されている let bar = obj as Bar // Bar クラス TypeCasting
  • 144. ダウンキャスト // obj には Base クラスのインスタンスが入っている // Base を継承した Bar クラスが定義されている let bar = obj as Bar もし obj に Bar へダウンキャストできないオブジェクトが入って いたらランタイムエラー TypeCasting
  • 145. ダウンキャスト // obj には Base クラスのインスタンスが入っている // Base を継承した Bar クラスが定義されている let bar = obj as? Bar オプショナルで安全 TypeCasting
  • 146. ダウンキャスト for obj in array { if obj is Bar { let bar = obj as Bar /* Snip */ } } TypeCasting for obj in array { if let bar = obj as? Bar { /* Snip */ } }
  • 147. ダウンキャスト for obj in array { if obj is Bar { let bar = obj as Bar /* Snip */ } } TypeCasting for obj in array { if let bar = obj as? Bar { /* Snip */ } } OptionalValue の評価式を使って、評価 > 代入が簡単に書ける
  • 148. 存在する演算子を拡張 @infix func + (left: String, right: Int) -> String { return "(left) (right)" } Operator Functions
  • 149. 存在する演算子を拡張 @infix func + (left: String, right: Int) -> String { return "(left) (right)" } “number” + 1 // “number 1” Operator Functions
  • 150. 存在しない演算子を定義 @infix func +++ (left: String, right: Int) -> String { return "(left) (right)" } “number” +++ 1 Operator Functions
  • 151. 存在しない演算子を定義 @infix func +++ (left: String, right: Int) -> String { return "(left) (right)" } “number” +++ 1 // コンパイルエラー Operator Functions
  • 152. 存在しない演算子を定義 operator infix +++ {} @infix func +++ (left: String, right: Int) -> String { return "(left) (right)" } “number” +++ 1 // “number 1” Operator Functions
  • 153. その他詳細は公式ドキュメントをご覧くだ さい。 https://developer.apple. com/library/prerelease/ios/documentation/swift/conceptual/swift_prog ramming_language/
  • 154. ドキュメントに見当たりません おまけ:正規表現
  • 155. えっ、、、 おまけ:正規表現
  • 156. NSRegularExpression を利用して Perl ライクな =~ 演算子を使えるようにするライブラリがあるの でとりあえず利用すると良さそう。 https://github.com/kasei/SwiftRegex おまけ:正規表現
  • 157. “Namespacing is implicit in swift, all classes (etc) are implicitly scoped by the module (Xcode target) they are in. no class prefixes needed” 「Swiftにおいて名前空間は暗黙のうちに提供される。すべてのクラ スはそのモジュール (Xcode上のターゲット)によって暗黙のうちに スコープが制限される。クラスプレフィックスはもはや不要」 via: https://twitter.com/clattner_llvm/status/474730716941385729 おまけ:名前空間
  • 158. アクセス修飾子 (private, public) おまけ:今後の展望
  • 159. アクセス修飾子 (private, public) "We don't usually promise anything for the future, but in this case we are making an exception. Swift will have access control mechanisms." 「将来の約束は一般的にしてないんだけど、今回は例外。Swift にはアクセス制限のための仕組みを追加予定です」 via: http://stackoverflow.com/questions/24003918/does-swift-have-access-modifiers おまけ:今後の展望
  • 160. CocoaPods おまけ:今後の展望
  • 161. CocoaPods https://github.com/CocoaPods/CocoaPods/tree/swift https://github.com/CocoaPods/CocoaPods/pull/2222 着々と進行中の様です。待ちましょう。 おまけ:今後の展望
  • 162. 汎用言語として公開してくれないかなー おまけ:今後の希望
  • 163. LINE Fukuoka では Swift なら誰にも負けないと いうエンジニアさんを求めています! 更におまけ
  • 164. 福岡で一緒に LINE を育てていきましょう! https://linefukuoka.co.jp/career/developer 更におまけ
  • 165. ご清聴ありがとうございました。