Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift on the ObjC #shibuyaswift

ainame
June 08, 2016

Swift on the ObjC #shibuyaswift

ainame

June 08, 2016
Tweet

More Decks by ainame

Other Decks in Programming

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  5. 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飯で過去に見た動画まとめ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  9. 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パターンを利用

    View full-size slide

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

    View full-size slide

  11. 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なやつ渡す❌

    View full-size slide

  12. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. 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'

    View full-size slide

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

    View full-size slide

  17. Current Status
    まだまだこれから

    View full-size slide

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

    View full-size slide

  19. Enjoy Swift!
    See you next week at WWDC!

    View full-size slide