Kyobashi.swift #1 に参加してきました

京橋でSwiftの勉強会が開催されたので行ってきました。 株式会社リクルートマーケティングパートナーズさんがスポンサーです。 会場は広くていい雰囲気。料理や飲み物がいっぱいだったのに無料でした。すごい! 人数は40人ぐらいでしょうか。結構多かった印象でした。
LTを行った後懇親会の流れでした。 LTのお題はこんな感じです。
| 発表者 | タイトル |
|---|---|
| yutu | About Kyobashi.swift#1 + Swift Refactoring Tips |
| akatsuki174 | 既存プロジェクトにSwiftLintを導入した話 |
| ktsukago | ExtraViewの使い方 |
| mpon | Unidirectional Data Flow in ReSwift |
| yousan | OSSから学ぶSwift実践テクニック |
| kazu0620 | Nearby Messages API |
| naoty | FriendlyErrorType |
| gomi_ningen | Dependency Injection in Swift 2.x |
自分もLTしてきました。
About Kyobashi.swift
\@yutu 平井祐樹
今回Kyobashi.swiftは1回目なので、このイベントの説明。 yutuさんは転職されたばかりで、kyobashi.dexを受けてSwift版を開催することにしたそうです。
おまけで次について発表されていました。
Refactoring Swift Source
Objective-Cでは使えたXcodeのRename機能ですが、Swiftでは使えません。そこでRefactorator Swift Pluginというのがあり、Alcatrazなどで入れられるそうです。
Xcode本体に早く入れて欲しい。
既存プロジェクトにSwiftLintを導入した話
\@akatsuki174
SwiftLintをプロジェクトに導入したときの話。いきなり導入するとワーニングがえらいことになるので、徐々にいれていこうっっていう話ですね。
SwiftLintはGitHubのコーディング規約がベースになっていて、そこからパラメータをカスタマイズしていくそうです。
ルールは.swiftlint.ymlに記述。RunScriptにLintを実行するよう追記。
導入ステップ 1. チームの合意を得る 2. 採用するルールを決める(line_lengthはチームで議論) 3. 全てのルールをdisabledにする 4. 1つずつルールを適用 5. 数値系ルールの値の調整 6. ユニットテストを回して確認
$ swiftlint autocorrect
を使うこともできるそうです。
ExtraViewの使い方
www.slideshare.net
\@ktsukago
ExtraViewの使い方についてご紹介(Swiftは関係ないと最初に宣言されていました笑)
Storyboardの外側にViewを持たせることができるという話です。発表にもありましたがSectionHeaderの定義に使うと便利そうです。
Viewをここに挿入できることは知っていたのですが、Storyboard Editorに表示されてましたっけ??Storyboardと一緒に編集できて便利ですね。
Unidirectional Data Flow in ReSwift
\@_mpon
ReSwiftについての説明。
ReSwiftはReduxのSwift実装で、ReduxはFluxを進化させたもので、FluxとはFacebookが提唱しているクライアントアプリケーションの設計モデルのこと。
- rackt/redux: Predictable state container for JavaScript apps
- Flux | Application Architecture for Building User Interfaces
ヘビーなフレームワークって導入コストも大きそうだけど、どうやって導入していってるんでしょう。聞いてみたかった。
OSSから学ぶSwift実践テクニック
ここは自分の発表をさせていただきました。 こちらに置いてあります。
Qiitaにも投稿してあるので、手早く読みたい人はこちらをどうぞ。
Alamofireから学ぶSwift実践テクニック - Qiita
Nearby Messages API
\@kazu0620
自己紹介されてましたが、個人アプリのDL数ハンパない。
Sansanさんの名刺交換アプリを作った際の話。名刺交換を様々なデバイスで行うことを考えた時に、こちらのGoogleのAPIを使うことを思いついたそうです。
Nearby Messages API Overview | Nearby Messages API | Google Developers
仕組みとしては、 1. 送信側がGoogleのAPIにアクセスして、渡す情報と一次的なペアリングコードを生成する。 2. 送信側はペアリングコードをBT, BLE, WiFi, 「超音波」などの方法で送信する。 3. 受信側はペアリングコードを受信する。 4. Googleでペアリングコードを確認し、紐付いた情報を取ってくる。
という流れの模様です。超音波が使えることで、BLEを持っていないAndroidとも情報交換できます。
注意として、100KBまで、常に送信し続けないようにする、Googleの許諾画面が出るといった項目があるそうです。
FriendlyErrorType
www.slideshare.net
\@naoty
従来のNSErrorからErrorTypeへ移行したときの工夫についてです。
ErrorTypeにはuserInfoのような詳細なエラー情報がないため、それを格納するプロパティを持った、ErrorType適合型を実装するとよいそうです。
さらに、Alamofireを使用したりすると、NSErrorがまだ使用されているのでErrorTypeとの共存を考える必要があるとのこと。NSErrorにextensionでFriendlyErrorTypeに適合させれば、NSErrorをFriendlyErrorTypeと同じように扱えるそうです。
Dependency Injection in Swift 2.x
\@gomi_ningen
複雑なDI(Dependency Injection)を解決するための話です。当日は理解まで追いつけなかったので、復習。
そもそもDIとは?
オブジェクトが他のオブジェクトを利用するコードを「依存性」と捉え、これらの依存性をもったコードを実行時に注入するため、依存性注入と呼ばれる。
例えばHTTPクライアントオブジェクトを内部プロパティに持ち、それを使ってリクエストを送信するオブジェクトをテストしたいとします。テスト用に応答を固定したいので、固定の応答を返すダミークライアントに変えたいのですが、Swiftで内部プロパティを直接書き換えられないので困ります。そういう時は、コンストラクタからHTTPクライアントを渡せるようにします。これがDIです。このケースは特に、Constructor Injectionというそうです。
オブジェクトが他のオブジェクトを利用するコードを「依存」していると呼び、上の例であれば「テストしたいオブジェクトは、HTTPクライアントオブジェクトに依存している」と言います。
この発表では、「じゃあAがBに依存していて、BがCに依存している関係があった場合、Aのテストする時、コンストラクタがC(B(A()))と、どんどん複雑になってしまう」という話。
動的DI
オブジェクトを生成する前に、依存関係を適宜登録するパターン。
Swinjectというライブラリの紹介。 Swinject/Swinject: Dependency injection framework for Swift
ここで上がってる例を見ると、
let container = Container()
container.register(AnimalType.self) { _ in Cat(name: "Mimi") }
container.register(PersonType.self) { r in
PetOwner(pet: r.resolve(AnimalType.self)!)
}
つまりPersonType -> PetOwner -> AnimalTypeと依存しており、あらかじめ初期化の流れを記述しておく。このcontainerを使ってインスタンスをこう生成できる。
let person = container.resolve(PersonType.self)! person.play() // prints "I'm playing with Mimi."
静的DI
型の定義で依存関係をコントロールするケース。
Cake Patternを参考に、Protocol Extensionを使って実現しています。Cake Patternを自分は知らなかったのですが、ScalaのMix機能を使って行うDIパターンのようです。
サンプルコードの方の最後の方を見ると、確かに実装するプロトコルで振る舞いを切り替えられているようです。
class DebugContext: DefaultAComponent, DefaultABComponent {
static let a: A = DebugContext.createA()
static let ab: AB = DebugContext.createAB()
}
class ReleaseContext: DefaultAComponent, SimpleABComponent {
static let a: A = ReleaseContext.createA()
static let ab: AB = ReleaseContext.createAB()
}
let debugContext = Context(type: DebugContext.self)
debugContext.ab.getAB()
let releaseContext = Context(type: ReleaseContext.self)
releaseContext.ab.getAB()
でも途中までのコードが複雑ですね。ちょっと悩ましい。
難しかったですが勉強になりました。
感想
いろんなレベル感のある発表があって面白かったです。懇親会もいろいろお話聞くことができました。次回もぜひ参加したいです。