type safe assets handling in swift

17
Type Safe Resource Handling in Swift 2015/10/13 potatotips #22

Upload: kazunobu-tasaka

Post on 14-Jan-2017

1.699 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: Type Safe Assets Handling in Swift

Type Safe Resource Handling in Swift

2015/10/13potatotips #22

Page 2: Type Safe Assets Handling in Swift

About Me

@tasanobu

Kazunobu Tasaka

Page 3: Type Safe Assets Handling in Swift

本日の内容

• リソースを静的型付けし、Type Safeに扱う方法をお話しします。

• リソースとはAsset Catalog  UIStoryboard Localizable.strings

Page 4: Type Safe Assets Handling in Swift

• リソースのインスタンス生成時String型の値で指定

Objective-C style

// Assets Catalog let img = UIImage(named: "Sample") // Storyboard let sb = UIStoryboard(name: "Sample", bundle: nil) .instantiateViewControllerWithIdentifier("Sample") as? SampleViewController // Localizable.strings let str = NSLocalizedString("Sample", comment: “")

Page 5: Type Safe Assets Handling in Swift

問題点• コンパイラによるチェックが不可

→ 指定方法がStringのため💦

• 実行時にリソースの存在チェック → ランタイムエラーが発生するリスクあり

• 戻り値の型 : Optional<T> → 使用時にunwrapする必要がある

// 存在しない場合 let sb = UIStoryboard(name: UIApplicationDidBecomeActiveNotification, bundle: nil) // Terminating app due to uncaught exception 'NSInvalidArgumentException', // reason: 'Could not find a storyboard named 'Sample' in bundle NSBundle

let img: UIImage? = UIImage(named: NSURLErrorDomain)

let vc: SampleViewController? = sb.instantiateViewControllerWithIdentifier("Sample") as? SampleViewController

Page 6: Type Safe Assets Handling in Swift

改善ポイント

Swift は Type Safe な言語!

• リソースのStringに型情報を持たせる

Page 7: Type Safe Assets Handling in Swift

App Specific Enum

extension UIImage { enum Asset: String { case Camera = "Camera" case Home = "Home" case Mail = "Mail" }

convenience init!(asset: Asset) { self.init(named: asset.rawValue) } }

Asset ID / Enumの対応付け

• Initializer: Enumでリソースを指定• Non Optional な戻り値 (リソースの存在が担保されている)

Page 8: Type Safe Assets Handling in Swift

Usage

let camera = UIImage(asset: .Camera)

let home = UIImage(asset: .Home)

let mail = UIImage(asset: .Mail)

Page 9: Type Safe Assets Handling in Swift

Pros / Cons• Pros

引数を型付けできる

→ コンパイル時チェックが可能

→ Non-optionalな型が戻り値となる

• Cons

リソースを更新する度にEnum値を更新する必要がある😓

Page 10: Type Safe Assets Handling in Swift

• CLツール : リソース用Swiftコードを自動生成

Asset Catalog (UIImage) UIStoryboard

Localizable.strings UIColor

• Homebrewに対応

https://github.com/AliSoftware/SwiftGen

SwiftGen

 $  brew  install  swiftgen  

Page 11: Type Safe Assets Handling in Swift

Usage: UIStoryboard

• コマンドラインを実行

swiftgen-­‐storyboard  /dir/to/storyboards  >  Storyboards.swift

Page 12: Type Safe Assets Handling in Swift

// Storyboards.swift

protocol StoryboardScene : RawRepresentable { static var storyboardName : String { get } static func storyboard() -> UIStoryboard static func initialViewController() -> UIViewController func viewController() -> UIViewController static func viewController(identifier: Self) -> UIViewController }

extension StoryboardScene where Self.RawValue == String { static func storyboard() -> UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: nil) } static func initialViewController() -> UIViewController { return storyboard().instantiateInitialViewController()! } func viewController() -> UIViewController { return Self.storyboard().instantiateViewControllerWithIdentifier(self.rawValue) } static func viewController(identifier: Self) -> UIViewController { return identifier.viewController() } }

via https://github.com/AliSoftware/SwiftGen

Page 13: Type Safe Assets Handling in Swift

// Storyboards.swift

extension UIStoryboard { struct Scene { enum Wizard : String, StoryboardScene { static let storyboardName = "Wizard" case CreateAccount = "CreateAccount" static func createAccountViewController() -> CreateAccViewController { return Wizard.CreateAccount.viewController() as! CreateAccViewController } case ValidatePassword = "Validate_Password" static func validatePasswordViewController() -> UIViewController { return Wizard.ValidatePassword.viewController() } } enum Message : String, StoryboardScene { static let storyboardName = "Message" case Composer = "Composer" static func composerViewController() -> UIViewController { return Message.Composer.viewController() } case URLChooser = "URLChooser" static func urlChooserViewController() -> XXPickerViewController { return Message.URLChooser.viewController() as! XXPickerViewController } } } struct Segue { enum Message : String { case Custom = "Custom" case Back = "Back" case NonCustom = "NonCustom" } } }

Storyboard IDに対応Storyboardファイルに対応

via https://github.com/AliSoftware/SwiftGen

Page 14: Type Safe Assets Handling in Swift

Usage// Initial VC let initialVC = UIStoryboard.Scene.Wizard.initialViewController()

// Generic ViewController constructor, returns a UIViewController instance let validateVC = UIStoryboard.Scene.Wizard.ValidatePassword.viewController()

// Dedicated type var that returns the right type of VC (CreateAccViewController here) let createVC = UIStoryboard.Scene.Wizard.createAccountViewController()

override func prepareForSegue(_ segue: UIStoryboardSegue, sender sender: AnyObject?) { switch UIStoryboard.Segue.Message(rawValue: segue.identifier)! { case .Custom: // Prepare for your custom segue transition case .Back: // Prepare for your custom segue transition case .NonCustom: // Prepare for your custom segue transition } }

via https://github.com/AliSoftware/SwiftGen

Page 15: Type Safe Assets Handling in Swift

まとめ• App Specific Enum を利用すると静的型付けしてリソースを扱える😄

• SwiftGen: リソース用コードを自動生成可能😄

Page 16: Type Safe Assets Handling in Swift

References

• SwiftGenhttps://github.com/AliSoftware/SwiftGen

• WWDC’15: Swift in Practice https://developer.apple.com/videos/wwdc/2015/?id=411

Page 17: Type Safe Assets Handling in Swift

ご静聴ありがとうございました

🙇