Slide 1

Slide 1 text

Swift on the ObjC Shibuya.swift#4 ● @ainame (Satoshi NAMAI) ● 株式会社ミクシィ ● 家族アルバムみてね作ってます

Slide 2

Slide 2 text

Question あなたのプロジェクトにはまだObjective-Cのコードがありますか?

Slide 3

Slide 3 text

Contents みてねチームにおいて、昨年10月頃からObjCで書かれたコードベースの上にSwift を書いてきた際に取り組んできたことを話します。

Slide 4

Slide 4 text

Policy ユーザーへの価値提供が第一 ● 全コードを一気にSwiftに置き換えることはしない ● 新規に書く箇所はSwift ● 大きく仕様変更が入る際には画面単位でSwiftに置き換えつつ レガシーな設計から良い設計に合わせていく

Slide 5

Slide 5 text

Study Swift by WWDC videos 毎週水曜にランチタイムにみんなで動画を見てSwift2について学んだ ● What's New in Swift ● Protocol-Oriented Programming in Swift ● Building Better Apps with Value Types in Swift ● Swift and Objective-C Interoperability see: 動画で学ぶモダンなiOS/Androidアプリ開発技術 - ainameの日記 井戸端iOS飯で過去に見た動画まとめ

Slide 6

Slide 6 text

Get started! ● Bridging HeaderでObjCのコードをimportしてSwiftを書き始める ● SwiftのStructやEnumはObjC側では使えないのでほとんど使わず、NSObject を継承 or @objcでClassを書いてく ● ObjCの巨大なViewControllerに機能追加する際には同じファイル名で extensionとして実装(⌥ + ↑ で切り替え可能) ○ SomeViewController.{h,m,swift}という感じで3ファイルが存在している状態

Slide 7

Slide 7 text

Xcode’s auto-completion ●Swift上でObjcのクラスの補完が効かなくなった Clean、Derived Data削除も効果なし importの仕方を修正したら復活 ✖ #import ◯ #import see: http://stackoverflow.com/a/35431971

Slide 8

Slide 8 text

Swifty? ● さらに動画でSwiftっぽい書き方を学ぶ ● "Feet in Both Worlds: From Objective-C to Swift" by Andy Matuschak ● Let's Play: Refactor the Mega Controller!

Slide 9

Slide 9 text

Example // enumを使ってUIの機能追加したい enum Icon { case Color(UIColor) case Image(UIImage) } class IconView: UIView { init(icon: Icon) { … } } // ObjC用の箱を用意しておく class Box { let value: T init(_ value: T) { self.value = value } } // ObjCのクラスには箱だけを id型としておいておく @interface LegacyViewController @property (readwrite, strong) id /* Box */ _icon; @end // 箱から取り出し用の propertyを宣言して extension LegacyViewController { var icon: Icon { get { return (_icon as! Box).value } set { _icon = Box(newValue) } } // すっきりした実装ができる func showProfileWithIcon(icon: Icon) } どうしてもSwiftでしか使えないやつをObjCのViewControllerに もたせたい場合はBoxパターンを利用

Slide 10

Slide 10 text

Nullability & Lightweight Generics ● SwiftでObjCのメソッドを呼ぶ際にNullabilityを考慮してなくて事故る ● Bridging Headerでimportされているものには必ずNullability + Lightweight Genericsを指定するルールに

Slide 11

Slide 11 text

Nullability & Lightweight Generics - Pitfall SwiftからObjCに公開するメソッドはnilが入り込みやすい (Swift側で参照すると落ちる) @objc func doSomething(string: String) ← 普通のSwiftのメソッ ド---------------------------------------------------------- NSString *str = [self textField.text]; ← TextFieldからnullableなNSStringをとる [obj doSomething:str]; ← Swiftのメソッドにnullableなやつ渡す❌

Slide 12

Slide 12 text

Carthage & Dynamic Framework ● SwiftベースのライブラリはDynamic Frameworkとして取り込んでいる ● Cocoapodsはuse_frameworks!できなかった時ように残してある (当時GoogleAnalytics SDKとか出来なかったけど今は対応している?) ● carthage bootstrapは初回こそ時間かかるものの一度ビルドすると再ビルドせ ず済むので良い ● CircleCI上でRxSwiftのビルド終わらない問題 ○ CI上でビルドせず最初から s3にビルド済みキャッシュを自前で置く戦略で・・・ ○ aws s3 sync s3://BUCKET/`md5 Cartfile.resolved | awk '{ print $4; }'` Carthage/Build/iOS

Slide 13

Slide 13 text

Introduce swifty libraries 置き換え系 ● SDWebImageから拝借したdispatch_sync_main_safe -> duemunk/Async ● DateTools -> malcommac/SwiftDate ● PromiseKit & KVOController -> ReactiveX/RxSwift 新規導入系 ● antitypical/Result, lyft/mapper, ra1028/Former

Slide 14

Slide 14 text

NSCoding & Unit testing シリアライズ処理は辛い(怖い) ● @objc(CLASS NAME)を利用してSwift化 ● Module名が異なるとクラス名が一緒でもforce downcastでクラッシュ 1. テスト対象クラスをTestのTargetにも追加 2. TestのtargetのModule名をアプリのTargetのModule名にして回避 ● アプリのTargetをModule化して@testable importする方が一般的っぽい?

Slide 15

Slide 15 text

Example @interface MTNFoo: NSObject @property(nonatomic) MTNBar *bar; .... @end @implementation MTNFoo - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [self init]; if (self) { _bar= [aDecoder ecodeObjectForKey:@"bar"]; } return self } @end @objc(MTNFoo) class MTNFoo: NSObjcet, NSCoding { var bar:MTNBar … required init?(coder aDecoder: NSCoder) { self.bar = aDecoder.decodeObjectForKey("bar") as! MTNBar } } MiteneTests -> Mitene Could not cast value of type MiteneTests.MTNBar' (0x13218604) to 'Mitene.MTNBar'

Slide 16

Slide 16 text

SwiftLint ● SwiftLintをフォーマッター的に利用 ● まだレビュー用途には利用できてない ● チームメンバーがXcodePlugin書いてくれた ○ ypresto/SwiftLintXcode: An Xcode plug-in to format your code using SwiftLint.

Slide 17

Slide 17 text

Current Status まだまだこれから

Slide 18

Slide 18 text

まとめ ● Swiftに慣れるのにみんなで動画を見るのはいいぞ ● Nullability頑張って定義していこう ● Xcodeの補完効かなくなると仕事出来なくなるので頑張って解決しよう ● ObjCと混ぜたプロジェクトでテスト書くの大変っぽい?

Slide 19

Slide 19 text

Enjoy Swift! See you next week at WWDC!