Swift おさらい
LINE Developer Meetup in Fukuoka #5
@taketin 2014/06/24
自己紹介
@taketin
LINE Fukuoka iOS developer
PHP, Ruby, Objective-C
(だいたい)毎週木曜19:30 〜
Fukuoka.swift よろしくお願いします
初めて買ったマック
Macin...
Swift とは?
https://developer.apple.com/swift/
http://swift-lang.org/main/
https://developer.apple.com/swift/
http://swift-lang.org/main/
◯
Swift is “Objective-C without the C”
• Swift言語の開発は2010年7月にAppleエンジニアの
個人プロジェクトから始まった
• 設計するにあたって影響を受けた言語は Objective-C、
Rus...
特徴
• モダン
クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。
via: http://ja.wikipedia.org/wiki/Swift_(プログラミング言語)
特徴
• モダン
クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。
• 安全
静的な型チェック、変数の初期化の強制、数値型のオーバーフローの検査、
自動参照カウント (ARC) によるメモリ管理など。
via: ht...
特徴
• モダン
クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。
• 安全
静的な型チェック、変数の初期化の強制、数値型のオーバーフローの検査、
自動参照カウント (ARC) によるメモリ管理など。
• 高速
Ob...
特徴
• モダン
クロージャやタプル、ジェネリックプログラミング、 Optional型の採用。
• 安全
静的な型チェック、変数の初期化の強制、数値型のオーバーフローの検査、
自動参照カウント (ARC) によるメモリ管理など。
• 高速
Ob...
では仕様を見ていきましょう
変数 (var)
var city: String = “Hakata”
変数、定数
変数 (var)
var city: String = “Hakata”
定数 (let)
let city: String = “Hakata”
city = “Tenjin” // error
変数、定数
変数 (var)
var city: String = “Hakata”
定数 (let)
let city: String = “Hakata”
city = “Tenjin” // error
型推論
var city = “Tenjin”...
変数名は日本語、ユニコード絵文字も
一部使用可。
var 街 = “博多”
変数、定数
暗黙の型変換はしない。
let label = "old"
let age = 36
String(age) + label
型変換
() で展開
var city = “Hakata”
“welcome to (city).”
変数展開
() で展開
var city = “Hakata”
“welcome to (city).”
式の評価もできる
var section = “Ekimae”
“welcome to (city + section).”
※ シングルクォートは...
nil 許容 (型の後ろに ? を付ける)
var optional: String = nil // error
Optional Value
nil 許容 (型の後ろに ? を付ける)
var optional: String = nil // error
var optional: String? = nil
通常、変数に nil を入れる事はできない。
Optional Value
var foo: String? = “bar” // {Some “bar”}
“指定された型の値”、もしくは “nil”
の2つの要素を持てるように曖昧な形に
「wrap」されている
という表現を使う。
Optional Value
「unwrap」する
var optional :String? = “foo” // {Some “foo”}
var notOptional = optional! // “foo”
ImplicitlyUnwrappedOptional
「unwrap」する
var optional :String? = “foo” // {Some “foo”}
var notOptional = optional! // “foo”
確実に nil では無いと判断できる場合のみ使用する。
...
特別な評価式
var optional :String? = “foo”
if let notOptional = optional {
println(“(notOptional) is not nil”)
} else {
println(...
? は enum Optional<T>
! は struct ImplicitlyUnwrappedOptional<T>
のシンタックスシュガー
ImplicitlyUnwrappedOptional
? は enum Optional<T>
! は struct ImplicitlyUnwrappedOptional<T>
のシンタックスシュガー
⌘ + Click で定義を見れるので、中身を
色々見て理解を深めましょう
Implicitl...
class Users {
class User {
var name: String = "taketin"
}
var user: User? = User()
}
OptionalChaining
class Users {
class User {
var name: String = "taketin"
}
var user: User? = User()
}
OptionalChaining
var users: Users? = ...
class Users {
class User {
var name: String = "taketin"
}
var user: User? = nil
}
OptionalChaining
var users: Users? = Use...
var response = (404, "NotFound")
Tuple
var response = (404, "NotFound")
response.0 // 404
response.1 // “NotFound”
Tuple
var response = (404, "NotFound")
response.0 // 404
response.1 // “NotFound”
// ラベル
response = (status:404, description:”No...
var response = (404, "NotFound")
response.0 // 404
response.1 // “NotFound”
// ラベル
response = (status:404, description:”No...
true or false
Bool値
true or false
YES or NO は無くなりました
Bool値
配列
var a = [1, 2, 3]
var b = String[]()
var c = Array<String>()
var d = Double[](count: 3, repeatedValue: 0.0)
// [0.0, 0....
配列イテレーション
var array = [1, 2, 3]
for value in array {
println(value)
}
コレクション
配列のコピー
var a = [1, 2, 3]
var b = a // [1, 2, 3] (参照渡し)
var a[0] = 9 // [9, 2, 3]
b // [9, 2, 3]
コレクション
配列のコピー
var a = [1, 2, 3]
var b = a // [1, 2, 3] (参照渡し)
a.append(4) // [1, 2, 3, 4]
b // [1, 2, 3]
コレクション
配列のコピー
var a = [1, 2, 3]
var b = a // [1, 2, 3] (参照渡し)
a.append(4) // [1, 2, 3, 4] (コピー作成)
b // [1, 2, 3]
配列長が変わると新しい配列を作る...
配列のコピー
var a = [1, 2, 3]
var b = a.copy() // 値渡し
コレクション
配列のコピー
var a = [1, 2, 3]
var b = a.copy() // 値渡し
または
var b = a
b.unshare() // 参照を切る
コレクション
配列範囲指定
var array = [1, 2, 3]
array[0..2] = [1] // [1, 3]
array[0...2] = [1] // [1]
コレクション
配列範囲指定
var array = [1, 2, 3]
array[0..2] = [1] // [1, 3]
array[0...2] = [1] // [1]
.. は未満 ... は以下(Rubyと逆なので注意)
コレクション
ディクショナリ
var a = Dictionary<Int, String>()
var b = [1:”foo”, 2:”bar”]
b[1] = nil // [2:”bar”]
コレクション
ディクショナリ
キーの型は hashable で無くてはならない。
String, Int, Double, Bool はデフォルトで
hashable (Hashable プロトコル継承)
コレクション
ディクショナリイテレーション
for (key, value) in dictionary {}
// キーのみ、値のみ
for key in dictionary.keys {}
for values in dictionary.values...
ディクショナリのコピー
var a = [1:”a”, 2:”b”]
var b = a // 値渡し
a[1] = “z” // [1:”z”, 2:”b”]
b // [1:”a”, 2:”b”]
コレクション
if文
if 条件式 {
/* Snip */
} else if 条件式 {
/* Snip */
}
コントロール
while文
while 条件式 {
/* Snip */
}
do {
/* Snip */
} while 条件式
コントロール
for文
for var index = 0; index < 5; index++ {
/* Snip */
}
for index in 0..5 {
/* Snip */
}
コントロール
switch文
let foo = "hoge"
switch foo {
case "bar":
println("bar")
case "baz", "hoge":
println("baz or hoge")
default:
print...
switch文
基本 break 動作。
fallthrough を指定すると次の case も処理。
コントロール
switch文 いろいろなマッチング
case 1...3: // Range
case (_, 0): // tuple
case (let x, 0): // value bindings
case let (x, y) where x =...
enum Fukuoka {
case Tenjin
case Daimyo
case Hakata
case Nakasu
}
列挙型 (Enum)
enum Fukuoka {
case Tenjin
case Daimyo
case Hakata
case Nakasu
}
列挙型 (Enum)
var foo = Fukuoka.Tenjin
switch foo {
case .Te...
enum Fukuoka {
case Tenjin
case Daimyo
case Hakata
case Nakasu
}
列挙型 (Enum)
var foo = Fukuoka.Tenjin
switch foo {
case .Te...
enum Rank: Int {
case One = 1
case Two, Three, Four
}
列挙型 (Enum)
enum Rank: Int {
case One = 1
case Two, Three, Four
}
var rank = Rank.Two // (Enum Value)
列挙型 (Enum)
enum Rank: Int {
case One = 1
case Two, Three, Four
}
var rank = Rank.Two // (Enum Value)
rank.toRaw() // 2
列挙型 (Enum)
enum Rank: Int {
case One = 1
case Two, Three, Four
}
var rank = Rank.Two // (Enum Value)
rank.toRaw() // 2
Rank.fromRaw(3...
enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
}
var city = Fukuoka.Hakata
列挙型 (Enum)
enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
}
var city = Fukuoka.Hakata
city = .Tenjin // 型が分かっているので省略可能
...
enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
func toKana() -> String {
switch self {
case .Tenjin: return ...
enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
func toKana() -> String {
switch self {
case .Tenjin: return ...
enum Fukuoka: String {
case Tenjin = "天神"
case Hakata = "博多"
func toKana() -> String {
switch self {
case .Tenjin: return ...
Associated Values
enum APIResponse {
case Success(Int, String)
case Error(Int, String, NSError)
}
列挙型 (Enum)
Associated Values
enum APIResponse {
case Success(Int, String)
case Error(Int, String, NSError)
}
// if success
var res = ...
Associated Values
enum APIResponse {
case Success(Int, String)
case Error(Int, String, NSError)
}
// if success
var res = ...
Associated Values
switch res {
case let .Success(httpStatus, message):
… // 成功時処理
case let .Error(httpStatus, message, err...
Associated Values
switch res {
case let .Success(httpStatus, message):
… // 成功時処理
case let .Error(httpStatus, message, err...
func foo(bar: String, baz: Int) -> String {}
関数
func foo(bar: String, baz: Int) -> String {}
// キーワード指定可
func foo(aaa bar: String, bbb baz: Int) -> String {}
関数
func foo(bar: String, baz: Int) -> String {}
// キーワード指定可
func foo(aaa bar: String, bbb baz: Int) -> String {}
// 引数のデフォルト値...
// 引数の可変長指定可 (Variadic Parameter)
func foo(bar: String, baz: Int...) -> String {}
関数
// 引数の可変長指定可 (Variadic Parameter)
func foo(bar: String, baz: Int...) -> String {}
// 引数の参照渡し (inoutラベル)
func swapValue(ino...
ネスト
func foo() -> Int {
func bar() {
func baz() {
}
baz()
}
bar()
}
foo()
関数
返り値が関数
func foo() -> ((Int, Int) -> String) {
func bar(number: Int, number2: Int) -> String {
return String(number + numbe...
返り値がタプル
func getTuple() -> (Double, Int, String) {
return (1.0, 2, "3")
}
var result = getTuple()
result.0 // 1.0
result.1...
基本形
sort([“A”, “C”, “B”], { (s1: String, s2: String) -> Bool in
return s1 < s2
})
// [“A”, “B”, “C”]
クロージャ
型推論が効く
sort([“A”, “C”, “B”], { (s1: String, s2: String) -> Bool in
return s1 < s2
})
▼
sort([“A”, “C”, “B”], { s1, s2 in
r...
式が1つだけの場合 return が省略できる
sort([“A”, “C”, “B”], { s1, s2 in
return s1 < s2
})
▼
sort([“A”, “C”, “B”], { s1, s2 in
s1 < s2
})...
引数をプレースホルダで置換できる
sort([“A”, “C”, “B”], { s1, s2 in
s1 < s2
})
▼
sort([“A”, “C”, “B”], { $0 < $1 })
クロージャ
Operator Functions を使用する
sort([“A”, “C”, “B”], { $0 < $1 })
▼
sort([“A”, “C”, “B”], < )
クロージャ
Operator Functions を使用する
sort([“A”, “C”, “B”], { $0 < $1 })
▼
sort([“A”, “C”, “B”], < )
式によってはここまで簡略化できる
クロージャ
Trailing Closures
sort([“A”, “C”, “B”], { $0 < $1 })
▼
sort([“A”, “C”, “B”]) { $0 < $1 }
クロージャ
Trailing Closures
sort([“A”, “C”, “B”], { $0 < $1 })
▼
sort([“A”, “C”, “B”]) { $0 < $1 }
引数の最後がクロージャの場合、外出し記述可
クロージャ
Trailing Closures
sort([“A”, “C”, “B”], { $0 < $1 })
▼
sort([“A”, “C”, “B”]) { $0 < $1 }
引数の最後がクロージャの場合、外出し記述可
sort([“A”, ...
blocks 内で self を使った場合の循環参照回避
// lang: Objective-C
__weak BlockOwner *weakSelf = self;
_block = ^() {
NSLog(@"name: %@", we...
blocks 内で self を使った場合の循環参照回避
// lang: Swift
self.aProperty = {
[unowned self] in // closure capture list
self.doSomething(...
blocks 内で self を使った場合の循環参照回避
// lang: Swift
self.aProperty = {
[unowned self] in // closure capture list
self.doSomething(...
class Foo {
var bar: String
init(baz: Int) { // コンストラクタ
self.bar = baz // propertyイニシャライズ必須
}
func hoge(fuga: Int, piyo: I...
コンストラクタ
init() がコンストラクタ
引数がある場合 init(baz: Int) はインスタンス生成時に引数ラ
ベルを指定する必要あり
var foo = Foo(baz: 1)
クラス
コンストラクタ
init() がコンストラクタ
引数がある場合 init(baz: Int) はインスタンス生成時に引数ラ
ベルを指定する必要あり
var foo = Foo(baz: 1)
ただし、_ をラベルにする事で回避できる
init(...
コンビニエンスコンストラクタ
class Foo {
var bar:Int
init(baz: Int) {
self.bar = baz
}
func hoge(fuga:Int, piyo:Int) {}
convenience init...
コンビニエンスコンストラクタ
var foo = Foo()
foo.bar // 0
コンストラクタ引数を省略する事ができる。その場合
convenience init 内に書かれた値で初期化される。
クラス
継承
class Foo : Bar {
}
クラス
継承
class Foo {
}
Objective-C と違い、基底クラスが無い場合は
継承を省略できる
クラス
メソッドオーバーライド
class Foo : Bar {
override func baz() {
}
}
クラス
メソッドオーバーライド
class Foo : Bar {
override func baz() {
}
}
スーパークラスと同名のメソッドを定義していても、
override が無ければ別メソッドとして認識される
クラス
コピー
var foo1 = FooClass()
foo1.bar // 10
var foo2 = foo1
foo2.bar // 10
クラス
コピー
var foo1 = FooClass()
foo1.bar // 10
var foo2 = foo1
foo2.bar // 10
foo1.bar = 50
foo2.bar // 50
クラス
コピー
var foo1 = FooClass()
foo1.bar // 10
var foo2 = foo1 // クラスは参照渡し
foo2.bar // 10
foo1.bar = 50
foo2.bar // 50
クラス
コピー
値渡しでコピーしたい場合は、
import Foundation して
NSCopying を継承。
copyWithZone() メソッドを自前で実装する。
(Objective-C と同じイメージ)
via: http://qiit...
比較 (===)
var foo1 = FooClass()
var foo2 = FooClass()
foo1 === foo2 // false
クラス
比較 (===)
var foo1 = FooClass()
var foo2 = FooClass()
foo1 === foo2 // false
var foo3 = foo1
foo3 === foo1 // true
クラス
比較 (===)
var foo1 = FooClass()
var foo2 = FooClass()
foo1 === foo2 // false
var foo3 = foo1
foo3 === foo1 // true
インスタンスのア...
Getter, Setter
class Foo {
var bar: Int {
get { return 10 }
set { self.baz = newValue }
}
var baz: Int = 0
}
クラス - プロパティ
Getter, Setter
class Foo {
var bar: Int {
get { return 10 }
set { self.baz = newValue }
}
var baz: Int = 0
}
setter は “new...
Getter, Setter
class Foo {
var bar: Int {
get { return 10 }
}
var baz: Int = 0
}
get のみ書く事で ReadOnly として定義できる
クラス - プロパティ
willSet, didSet
class Foo {
var bar:Int {
willSet {}
didSet {}
}
}
Objective-C の KVO のような動きができる
クラス - プロパティ
遅延ロード
class Foo {
@lazy var bar = SomeClass()
}
var foo = Foo() // ここでは bar 未初期化
foo.bar // ここで bar 初期化
クラス - プロパティ
Type Property Syntax
class Foo {
class var bar:Int {
return 1
}
}
Foo.bar // 1
クラス - プロパティ
class Foo {
var bar:Int = 5
init() {}
subscript(index: Int) -> Int {
return self.bar * index
}
}
Subscript
class Foo {
var bar:Int = 5
init() {}
subscript(index: Int) -> Int {
return self.bar * index
}
}
var foo = Foo();
foo[10] ...
class Foo {
var bar:Int = 5
init() {}
subscript(index: Int) -> Int {
get { /* Snip */ }
set { /* Snip */ }
}
}
アクセスコントロールも...
イニシャライズ
struct Foo {
var bar: Int = 1
func baz() -> String {
return "test"
}
}
var foo = Foo()
構造体 (Structure)
イニシャライズ
struct Foo {
var bar: Int
func baz() -> String {
return "test"
}
}
var foo = Foo(bar: 1)
構造体 (Structure)
mutating
struct Foo {
var bar: Int = 1
func baz() {
bar = 10 // コンパイルエラー
}
}
構造体 (Structure)
mutating
struct Foo {
var bar: Int = 1
mutating func baz() {
bar = 10
}
}
構造体 (Structure)
static variable
struct Foo {
static var bar: Int = 1
}
Foo.bar // 1
構造体 (Structure)
コピー
var foo1 = Foo()
foo1.bar // 1
var foo2 = foo1
foo1.bar = 10
構造体 (Structure)
コピー
var foo1 = Foo()
foo1.bar // 1
var foo2 = foo1
foo1.bar = 10
foo2.bar // 1
構造体は値渡し(クラスは参照)
構造体 (Structure)
protocol FooProtocol {
var bar: String { get }
func baz() -> String
}
Protocol
protocol FooProtocol {
var bar: String { get }
func baz() -> String
}
class FooClass : FooProtocol {
var bar: String = “ho...
protocol FooProtocol {
var bar: String { get set } // getter, setter 必須
func baz() -> String
}
class FooClass : FooProtoco...
protocol FooProtocol {
var bar: String
mutating func baz() -> String
}
struct FooStruct : FooProtocol {
var bar: String = ...
protocol FooProtocol {
}
protocol BarProtocol {
}
class FooClass : FooProtocol, BarProtocol {
/* Snip */
}
複数継承も可能
Protocol
extension String {
func twice() -> String {
return "(self) (self)"
}
}
Extention
extension String {
func twice() -> String {
return "(self) (self)"
}
}
var str = “hello”
str.twice() // “hello hello”
クラスだ...
extension String : FooProtocol {
func twice() -> String {
return "(self) (self)"
}
}
プロトコルの継承もできる
Extention
func Foo <任意の型> () {}
型の形式は UpperCamelCase。<HogeType> など。
短く <T> 等が慣習的に使われている。
Generics
型制約無し
func repeat<T>(item: T, times: Int) -> T[] {
var result = T[]()
for i in 0..times {
result += item
}
return result
}...
型制約無し
func repeat<T>(item: T, times: Int) -> T[] {
var result = T[]()
for i in 0..times {
result += item
}
return result
}...
型制約無し
func repeat<T>(item: T, times: Int) -> T[] {
var result = T[]()
for i in 0..times {
result += item
}
return result
}...
型制約有り
func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value...
型制約有り
func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value...
Any & AnyObject
var array : Any[] = ["1", 2, Foo()]
TypeCasting
Any & AnyObject
// 関数型以外なんでも入れる事ができる
var array : Any[] = ["1", 2, Foo()]
TypeCasting
Any & AnyObject
// 関数型以外なんでも入れる事ができる
var array : Any[] = ["1", 2, Foo()]
var array2 : AnyObject[] = [Foo(), Bar(), Baz()]
...
Any & AnyObject
// 関数型以外なんでも入れる事ができる
var array : Any[] = ["1", 2, Foo()]
// クラスのインスタンスのみ入れる事ができる
var array2 : AnyObject[] ...
型チェック
var array : Any[] = ["1", 2, 3]
for obj in array {
if obj is Int {
println("(obj) is Int") // 2 is Int & 3 is Int
}
...
ダウンキャスト
// obj には Base クラスのインスタンスが入っている
// Base を継承した Bar クラスが定義されている
let bar = obj as Bar // Bar クラス
TypeCasting
ダウンキャスト
// obj には Base クラスのインスタンスが入っている
// Base を継承した Bar クラスが定義されている
let bar = obj as Bar
もし obj に Bar へダウンキャストできないオブジェクト...
ダウンキャスト
// obj には Base クラスのインスタンスが入っている
// Base を継承した Bar クラスが定義されている
let bar = obj as? Bar
オプショナルで安全
TypeCasting
ダウンキャスト
for obj in array {
if obj is Bar {
let bar = obj as Bar
/* Snip */
}
}
TypeCasting
for obj in array {
if let bar =...
ダウンキャスト
for obj in array {
if obj is Bar {
let bar = obj as Bar
/* Snip */
}
}
TypeCasting
for obj in array {
if let bar =...
存在する演算子を拡張
@infix func + (left: String, right: Int) -> String {
return "(left) (right)"
}
Operator Functions
存在する演算子を拡張
@infix func + (left: String, right: Int) -> String {
return "(left) (right)"
}
“number” + 1 // “number 1”
Opera...
存在しない演算子を定義
@infix func +++ (left: String, right: Int) -> String {
return "(left) (right)"
}
“number” +++ 1
Operator Funct...
存在しない演算子を定義
@infix func +++ (left: String, right: Int) -> String {
return "(left) (right)"
}
“number” +++ 1 // コンパイルエラー
Op...
存在しない演算子を定義
operator infix +++ {}
@infix func +++ (left: String, right: Int) -> String {
return "(left) (right)"
}
“number...
その他詳細は公式ドキュメントをご覧くだ
さい。
https://developer.apple.
com/library/prerelease/ios/documentation/swift/conceptual/swift_prog
ramm...
ドキュメントに見当たりません
おまけ:正規表現
えっ、、、
おまけ:正規表現
NSRegularExpression を利用して Perl ライクな
=~ 演算子を使えるようにするライブラリがあるの
でとりあえず利用すると良さそう。
https://github.com/kasei/SwiftRegex
おまけ:正規表現
“Namespacing is implicit in swift, all classes (etc) are implicitly
scoped by the module (Xcode target) they are in. no cl...
アクセス修飾子 (private, public)
おまけ:今後の展望
アクセス修飾子 (private, public)
"We don't usually promise anything for the future, but in this
case we are making an exception. ...
CocoaPods
おまけ:今後の展望
CocoaPods
https://github.com/CocoaPods/CocoaPods/tree/swift
https://github.com/CocoaPods/CocoaPods/pull/2222
着々と進行中の様です。待ち...
汎用言語として公開してくれないかなー
おまけ:今後の希望
LINE Fukuoka では Swift なら誰にも負けないと
いうエンジニアさんを求めています!
更におまけ
福岡で一緒に LINE を育てていきましょう!
https://linefukuoka.co.jp/career/developer
更におまけ
ご清聴ありがとうございました。
Upcoming SlideShare
Loading in...5
×

Swiftおさらい

11,492

Published on

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

Published in: Travel, Technology
0 Comments
42 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
11,492
On Slideshare
0
From Embeds
0
Number of Embeds
13
Actions
Shares
0
Downloads
41
Comments
0
Likes
42
Embeds 0
No embeds

No notes for slide

Transcript of "Swiftおさらい"

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

    Clipping is a handy way to collect important slides you want to go back to later.

×