狠狠撸

狠狠撸Share a Scribd company logo
Type Safe Resource Handling
in Swift
2015/10/13
potatotips #22
About Me
@tasanobu
Kazunobu Tasaka
本日の内容
? リソースを静的型付けし、Type Safeに扱う方法
をお話しします。
? リソースとは?
Asset Catalog ?UIStoryboard ?
Localizable.strings
? リソースのインスタンス生成時?
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: “")
問題点
? コンパイラによるチェックが不可 ?
→ 指定方法が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
改善ポイント
Swift は Type Safe な言語!
? リソースのStringに型情報を持たせる
App Speci?c 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 な戻り値 (リソースの存在が担保されている)
Usage
let camera = UIImage(asset: .Camera)
let home = UIImage(asset: .Home)
let mail = UIImage(asset: .Mail)
Pros / Cons
? Pros
引数を型付けできる
→ コンパイル時チェックが可能
→ Non-optionalな型が戻り値となる
? Cons
リソースを更新する度にEnum値を更新する必要がある?
? CLツール : リソース用Swiftコードを自動生成
Asset Catalog (UIImage) UIStoryboard
Localizable.strings UIColor
? Homebrewに対応?
https://github.com/AliSoftware/SwiftGen
SwiftGen
	
 ?$	
 ?brew	
 ?install	
 ?swiftgen	
 ?
Usage: UIStoryboard
? コマンドラインを実行
swiftgen-?‐storyboard	
 ?/dir/to/storyboards	
 ?>	
 ?Storyboards.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
// 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
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
まとめ
? App Speci?c Enum を利用すると?
静的型付けしてリソースを扱える?
? SwiftGen: リソース用コードを自動生成可能?
References
? SwiftGen?
https://github.com/AliSoftware/SwiftGen?
?
? WWDC’15: Swift in Practice?
https://developer.apple.com/videos/wwdc/
2015/?id=411
ご静聴ありがとうございました
?

More Related Content

What's hot (11)

PPTX
忙しい人のための叠补肠办产辞苍别.箩蝉と础苍驳耻濒补谤.箩蝉入门
Toshiaki Maki
?
PDF
これからの闯补惫补厂肠谤颈辫迟の话
Shogo Sensui
?
PPT
20130924 Picomon CRH勉強会
Yukihiro Kitazawa
?
PDF
introduction to Marionette.js (jscafe14)
Ryuma Tsukano
?
PPTX
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
Kazuyoshi Kamitsukasa
?
PPTX
Marionettejs getting started
Kyohei Morimoto
?
PDF
BACKBONE.JSにJasmineでテストコード書いてみた (LT資料)
Toshio Ehara
?
PPTX
JAWS-UG CLI #14 LT 【”Waiters”機能の使いドコロ】
Ayumi Kobukata
?
PDF
NoSQL and JavaScript 2013-02-09
WakandaJA
?
PDF
齿滨叠で作ったカスタムセルの扱い方
Satoshi Anai
?
PDF
覚醒!闯补惫补厂肠谤颈辫迟
Haraguchi Go
?
忙しい人のための叠补肠办产辞苍别.箩蝉と础苍驳耻濒补谤.箩蝉入门
Toshiaki Maki
?
これからの闯补惫补厂肠谤颈辫迟の话
Shogo Sensui
?
20130924 Picomon CRH勉強会
Yukihiro Kitazawa
?
introduction to Marionette.js (jscafe14)
Ryuma Tsukano
?
jvmlang.daitokai 1.0.0 MinCamlJを作ってみた
Kazuyoshi Kamitsukasa
?
Marionettejs getting started
Kyohei Morimoto
?
BACKBONE.JSにJasmineでテストコード書いてみた (LT資料)
Toshio Ehara
?
JAWS-UG CLI #14 LT 【”Waiters”機能の使いドコロ】
Ayumi Kobukata
?
NoSQL and JavaScript 2013-02-09
WakandaJA
?
齿滨叠で作ったカスタムセルの扱い方
Satoshi Anai
?
覚醒!闯补惫补厂肠谤颈辫迟
Haraguchi Go
?

Viewers also liked (11)

PDF
Objective-C Generics
Goichi Hirakawa
?
PDF
My first tvOS
toyship
?
PDF
个人て?开発したアフ?リか?ヘ?スト新着に选は?れた话
Motoki Narita
?
PDF
Caffeでお手軽本格ディープラーニングアプリ @potatotips
Takuya Matsuyama
?
PDF
Introducing Cardio
Yusuke Kita
?
PDF
齿肠辞诲别7时代のアプリ配布
toyship
?
PDF
Swift Scriptingのすゝめ
Yuichiro Takahashi
?
PDF
View Monitoring Tips
Daisuke Yamashita
?
PDF
贬别补濒迟丑碍颈迟て?日别のテ?ータを一度に取得する
今城 善矩
?
PDF
watchOS2 tips
Motoki Narita
?
PDF
迟惫翱厂ネイティブアプリを作る
Tomoki Hasegawa
?
Objective-C Generics
Goichi Hirakawa
?
My first tvOS
toyship
?
个人て?开発したアフ?リか?ヘ?スト新着に选は?れた话
Motoki Narita
?
Caffeでお手軽本格ディープラーニングアプリ @potatotips
Takuya Matsuyama
?
Introducing Cardio
Yusuke Kita
?
齿肠辞诲别7时代のアプリ配布
toyship
?
Swift Scriptingのすゝめ
Yuichiro Takahashi
?
View Monitoring Tips
Daisuke Yamashita
?
贬别补濒迟丑碍颈迟て?日别のテ?ータを一度に取得する
今城 善矩
?
watchOS2 tips
Motoki Narita
?
迟惫翱厂ネイティブアプリを作る
Tomoki Hasegawa
?
Ad

Similar to Type Safe Assets Handling in Swift (20)

PPTX
颈笔丑辞苍别アフ?リ开発の歩き方?厂飞颈蹿迟编?
Yusuke SAITO
?
PDF
Storyboard
Hidetoshi Mori
?
PDF
厂飞颈蹿迟のアプリ开発でハマったこと
yohei sugigami
?
PDF
ようこそ! Swift Playgroundsへ
KinkumaDesign
?
PDF
Wolcome to swift
Kyohei Ito
?
PDF
厂飞颈蹿迟入门
聡 中川
?
PDF
Swift事情2014夏 ~ 厂飞颈蹿迟入门 beta6対応
Tomoki Hasegawa
?
PDF
I phoneアプリ入門 第4回
Sachiko Kajishima
?
PDF
厂飞颈蹿迟と颁辞肠辞补笔辞诲蝉て?始めるサクサク颈翱厂开発!
Koji Shiraishi
?
PDF
NS Prefix - そこから見渡す Swift 3 の景色 #startup_mobile
Tomohiro Kumagai
?
PDF
Storyboard
Akura Pi
?
PDF
これからはじめる SwiftPlayground入門
Hiramatsu Ryosuke
?
PDF
Study Swift
Akihiro Urushihara
?
PDF
厂飞颈蹿迟勉强会
Nagamine Hiromasa
?
PDF
厂飞颈蹿迟の概要をザックリと
Keisuke Tanaka
?
PDF
Storyboard
Yukihiko Kagiyama
?
PDF
齿肠辞诲别プラグインで快适な开発ライフを
Yuki Hirai
?
PDF
迟谤测!蝉飞颈蹿迟必见5选
Kenta Kudo
?
PDF
Embedded framework and so on
toyship
?
PDF
iOS 8/Swift 概要 #ios8yahoo
Hiramatsu Ryosuke
?
颈笔丑辞苍别アフ?リ开発の歩き方?厂飞颈蹿迟编?
Yusuke SAITO
?
Storyboard
Hidetoshi Mori
?
厂飞颈蹿迟のアプリ开発でハマったこと
yohei sugigami
?
ようこそ! Swift Playgroundsへ
KinkumaDesign
?
Wolcome to swift
Kyohei Ito
?
厂飞颈蹿迟入门
聡 中川
?
Swift事情2014夏 ~ 厂飞颈蹿迟入门 beta6対応
Tomoki Hasegawa
?
I phoneアプリ入門 第4回
Sachiko Kajishima
?
厂飞颈蹿迟と颁辞肠辞补笔辞诲蝉て?始めるサクサク颈翱厂开発!
Koji Shiraishi
?
NS Prefix - そこから見渡す Swift 3 の景色 #startup_mobile
Tomohiro Kumagai
?
Storyboard
Akura Pi
?
これからはじめる SwiftPlayground入門
Hiramatsu Ryosuke
?
Study Swift
Akihiro Urushihara
?
厂飞颈蹿迟勉强会
Nagamine Hiromasa
?
厂飞颈蹿迟の概要をザックリと
Keisuke Tanaka
?
齿肠辞诲别プラグインで快适な开発ライフを
Yuki Hirai
?
迟谤测!蝉飞颈蹿迟必见5选
Kenta Kudo
?
Embedded framework and so on
toyship
?
iOS 8/Swift 概要 #ios8yahoo
Hiramatsu Ryosuke
?
Ad

Recently uploaded (6)

PDF
AWS BedrockによるIoT実装例紹介とAI進化の展望@AWS Summit ExecLeaders Scale Session
Osaka University
?
PDF
React Native vs React Lynx (React Native Meetup #22)
Taiju Muto
?
PDF
【础滨罢搁滨翱厂】人惫蝉生成础滨でジェスチャーゲームを础滨罢滨搁翱厂を使ってしてみた
ueda0116
?
PDF
フィシ?カル础滨时代のセキュリティ:ロホ?ティクスと础滨セキュリティの融合のあり方
Osaka University
?
PDF
音学シンポジウム2025 招待讲演 远隔会话音声认识のための音声强调フロントエント?:概要と我々の取り组み
Tsubasa Ochiai
?
PPTX
[Liberaware] Engineer Summer Internship.pptx
koyamakohei
?
AWS BedrockによるIoT実装例紹介とAI進化の展望@AWS Summit ExecLeaders Scale Session
Osaka University
?
React Native vs React Lynx (React Native Meetup #22)
Taiju Muto
?
【础滨罢搁滨翱厂】人惫蝉生成础滨でジェスチャーゲームを础滨罢滨搁翱厂を使ってしてみた
ueda0116
?
フィシ?カル础滨时代のセキュリティ:ロホ?ティクスと础滨セキュリティの融合のあり方
Osaka University
?
音学シンポジウム2025 招待讲演 远隔会话音声认识のための音声强调フロントエント?:概要と我々の取り组み
Tsubasa Ochiai
?
[Liberaware] Engineer Summer Internship.pptx
koyamakohei
?

Type Safe Assets Handling in Swift

  • 1. Type Safe Resource Handling in Swift 2015/10/13 potatotips #22
  • 3. 本日の内容 ? リソースを静的型付けし、Type Safeに扱う方法 をお話しします。 ? リソースとは? Asset Catalog ?UIStoryboard ? Localizable.strings
  • 4. ? リソースのインスタンス生成時? 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: “")
  • 5. 問題点 ? コンパイラによるチェックが不可 ? → 指定方法が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
  • 6. 改善ポイント Swift は Type Safe な言語! ? リソースのStringに型情報を持たせる
  • 7. App Speci?c 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 な戻り値 (リソースの存在が担保されている)
  • 8. Usage let camera = UIImage(asset: .Camera) let home = UIImage(asset: .Home) let mail = UIImage(asset: .Mail)
  • 9. Pros / Cons ? Pros 引数を型付けできる → コンパイル時チェックが可能 → Non-optionalな型が戻り値となる ? Cons リソースを更新する度にEnum値を更新する必要がある?
  • 10. ? CLツール : リソース用Swiftコードを自動生成 Asset Catalog (UIImage) UIStoryboard Localizable.strings UIColor ? Homebrewに対応? https://github.com/AliSoftware/SwiftGen SwiftGen ?$ ?brew ?install ?swiftgen ?
  • 12. // 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
  • 13. // 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
  • 14. 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
  • 15. まとめ ? App Speci?c Enum を利用すると? 静的型付けしてリソースを扱える? ? SwiftGen: リソース用コードを自動生成可能?
  • 16. References ? SwiftGen? https://github.com/AliSoftware/SwiftGen? ? ? WWDC’15: Swift in Practice? https://developer.apple.com/videos/wwdc/ 2015/?id=411