Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Statically-typed Swifty APIs
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Radek Pietruszewski
September 15, 2016
Programming
0
96
Statically-typed Swifty APIs
A talk from NSSpain 2016
Radek Pietruszewski
September 15, 2016
Tweet
Share
More Decks by Radek Pietruszewski
See All by Radek Pietruszewski
Dependent Types
radex
0
38
Other Decks in Programming
See All in Programming
Basic Architectures
denyspoltorak
0
670
Spinner 軸ズレ現象を調べたらレンダリング深淵に飲まれた #レバテックMeetup
bengo4com
1
230
2026年 エンジニアリング自己学習法
yumechi
0
130
CSC307 Lecture 04
javiergs
PRO
0
660
OSSとなったswift-buildで Xcodeのビルドを差し替えられるため 自分でXcodeを直せる時代になっている ダイアモンド問題編
yimajo
3
620
AI時代のキャリアプラン「技術の引力」からの脱出と「問い」へのいざない / tech-gravity
minodriven
21
7.2k
Architectural Extensions
denyspoltorak
0
290
なるべく楽してバックエンドに型をつけたい!(楽とは言ってない)
hibiki_cube
0
140
AI によるインシデント初動調査の自動化を行う AI インシデントコマンダーを作った話
azukiazusa1
1
730
組織で育むオブザーバビリティ
ryota_hnk
0
180
AI & Enginnering
codelynx
0
110
それ、本当に安全? ファイルアップロードで見落としがちなセキュリティリスクと対策
penpeen
7
3.9k
Featured
See All Featured
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
0
140
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
130
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
0
3.4k
My Coaching Mixtape
mlcsv
0
48
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
220
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
KATA
mclloyd
PRO
34
15k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
9.9k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Building Adaptive Systems
keathley
44
2.9k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Transcript
Statically-typed Swifty APIs Radek Pietruszewski @radexp • radex.io
@radexp • radex.io Dynamic vs static
@radexp • radex.io Modern static typing
@radexp • radex.io
@radexp • radex.io NSUserDefaults Case study
@radexp • radex.io NSUserDefaults.standardUserDefaults() .stringForKey("color") NSUserDefaults.standardUserDefaults() .setObject(NSDate(), forKey: "updatedAt")
@radexp • radex.io let Defaults = NSUserDefaults.standardUserDefaults() Defaults.integer(forKey: "launchCount") #Courage
@radexp • radex.io Defaults.integer(forKey: "launchCount") Defaults.set("red", forKey: "color") let dictionary
= ["launchCount": 10] dictionary["launchCount"] dictionary["color"] = "red"
@radexp • radex.io extension UserDefaults { subscript(key: String) -> AnyObject?
{ get { return object(forKey: key) } set { set(newValue, forKey: key) } } } Defaults["color"] Defaults["color"] = "red"
@radexp • radex.io Defaults["color"] // AnyObject?
@radexp • radex.io Defaults["color"] // AnyObject?
@radexp • radex.io extension UserDefaults { subscript(key: String) -> Proxy
{ return Proxy(self, key) } }
@radexp • radex.io class Proxy { var string: String? {
return defaults.string(forKey: key) } var int: Int { return defaults.integer(forKey: key) } }
@radexp • radex.io Defaults["color"].string Defaults["launchCount"].int
@radexp • radex.io extension UserDefaults { subscript(key: String) -> Any?
{ set { if let v = newValue as? String { set(v, forKey: key) } else if let v = newValue as? Int { set(v, forKey: key) } } } }
@radexp • radex.io Common use cases
@radexp • radex.io Defaults["launchCount"] = Defaults["launchCount"].intValue + 1
@radexp • radex.io Defaults["launchCount"] += 1
@radexp • radex.io func += (proxy: UserDefaults.Proxy, b: Int) {
let a = proxy.defaults[proxy.key].intValue proxy.defaults[proxy.key] = a + b }
@radexp • radex.io postfix func ++ (proxy: UserDefaults.Proxy) { proxy
+= 1 }
@radexp • radex.io Defaults["launchCount"]++
@radexp • radex.io Defaults["launchCount"]++
@radexp • radex.io Defaults["launchCount"] += 1
@radexp • radex.io let defaults = NSUserDefaults.standardUserDefaults() defaults.setInteger( defaults.integerForKey("launchCount") +
1, forKey: "launchCount")
@radexp • radex.io Defaults["launchCount"] += 1
@radexp • radex.io Initial results
@radexp • radex.io Defaults["color"].string Defaults["launchCount"].int ?? 0 Defaults["launchCount"].intValue
@radexp • radex.io Defaults["color"] = "red" Defaults["totalTime"] += 3600
@radexp • radex.io But is this really Swifty?
@radexp • radex.io Defaults["color"] = "red"
@radexp • radex.io Defaults["color"] = "red" Defaults["colour"].string // => nil
@radexp • radex.io Defaults["deadline"] = Date.distantFuture Defaults["deadline"].data // => nil
@radexp • radex.io Defaults["deadline"] = Data() Defaults["deadline"].date // => nil
@radexp • radex.io Defaults["magic"] = 3.14 Defaults["magic"] += 10 Defaults["magic"]
// => 13
@radexp • radex.io Happens all the time!
@radexp • radex.io Fast feedback
@radexp • radex.io Refactoring
@radexp • radex.io The power of static typing
@radexp • radex.io let colorKey = "color"
@radexp • radex.io class DefaultsKey<ValueType> { let key: String }
@radexp • radex.io class DefaultsKey<ValueType> { let key: String }
let colorKey = DefaultsKey<String?>("color")
@radexp • radex.io let colorKey = DefaultsKey<String?>("color") extension UserDefaults {
subscript(key: DefaultsKey<String?>) -> String? { get { return string(forKey: key.key) } set { set(newValue, forKey: key.key) } } }
@radexp • radex.io Defaults[colorKey] = "green" Defaults[colorKey] // => "green"
: String? let colorKey = DefaultsKey<String?>("color")
@radexp • radex.io Defaults[colorKey] = "green" Defaults[colorKey] // => "green"
: String? let colorKey = DefaultsKey<String?>("color")
@radexp • radex.io Subscripts are awesome
@radexp • radex.io var array = [1, 2, 3] array.first!
+= 10
@radexp • radex.io var array = [1, 2, 3] array[0]
+= 10 array // => [11, 2, 3]
@radexp • radex.io var array = [1, 2, 3] array[0]
+= 10 array // => [11, 2, 3]
@radexp • radex.io subscript(...) -> ... { get { ...
} set { ... } }
@radexp • radex.io array[0] += 10
@radexp • radex.io var temp = array[0] temp += 10
array[0] = temp
@radexp • radex.io Defaults[launchCountKey] += 1 Defaults[volumeKey] -= 0.1 Defaults[favoriteColorsKey].append("green")
Defaults[stringKey] += "… can be extended!"
@radexp • radex.io Defaults["color"] Defaults[Keys.color]
@radexp • radex.io Implicit member expressions
@radexp • radex.io turn(Direction.left) turn(.left)
@radexp • radex.io CGRect.zero -> .zero
@radexp • radex.io DefaultsKey.color -> .color
@radexp • radex.io extension DefaultsKeys { static let color =
DefaultsKey<String>("color") }
@radexp • radex.io extension DefaultsKeys { static let color =
DefaultsKey<String>("color") } Defaults[.color] = "red"
@radexp • radex.io Defaults[.color] = "red"
@radexp • radex.io let key = DefaultsKey<[String]>("colors") Defaults[key].append("red") let red
= Defaults[key][0]
@radexp • radex.io extension DefaultsKeys { static let color =
DefaultsKey<NSColor?>("color") } Defaults[.color] // => nil Defaults[.color] = .white Defaults[.color] // => w 1.0, a 1.0 Defaults[.color]?.whiteComponent // => 1.0
@radexp • radex.io Result: SwiftyUserDefaults
@radexp • radex.io extension DefaultsKeys { static let username =
DefaultsKey<String?>("username") static let launchCount = DefaultsKey<Int>("launchCount") static let libraries = DefaultsKey<[String]>("libraries") static let color = DefaultsKey<NSColor?>("color") }
@radexp • radex.io Defaults[.username] Defaults[.username] = "radex" Defaults[.launchCount] // Int,
defaults to 0
@radexp • radex.io Defaults[.launchCount] += 1 Defaults[.volume] -= 0.1 Defaults[.strings]
+= "… can be extended!"
@radexp • radex.io Defaults[.libraries].append("SwiftyUserDefaults") Defaults[.libraries][0] += " 2.0"
@radexp • radex.io Defaults[.color] = .white Defaults[.color]?.whiteComponent // => 1.0
@radexp • radex.io Static typing doesn't hurt in Swift
@radexp • radex.io Small price to opt in
@radexp • radex.io Free gifts from the compiler
@radexp • radex.io Compile-time checks
@radexp • radex.io Autocompletion
@radexp • radex.io Inferred types
@radexp • radex.io Plays nicely with value types
@radexp • radex.io Swifty APIs use static typing
@radexp • radex.io Modern type systems are nice
@radexp • radex.io github.com/radex/ SwiftyUserDefaults