Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Statically-typed Swifty APIs
Search
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
マスタデータ問題、マイクロサービスでどう解くか
kts
0
110
TUIライブラリつくってみた / i-just-make-TUI-library
kazto
1
400
チームをチームにするEM
hitode909
0
350
複数人でのCLI/Infrastructure as Codeの暮らしを良くする
shmokmt
5
2.3k
【Streamlit x Snowflake】データ基盤からアプリ開発・AI活用まで、すべてをSnowflake内で実現
ayumu_yamaguchi
1
120
手が足りない!兼業データエンジニアに必要だったアーキテクチャと立ち回り
zinkosuke
0
760
認証・認可の基本を学ぼう後編
kouyuume
0
240
令和最新版Android Studioで化石デバイス向けアプリを作る
arkw
0
410
Tinkerbellから学ぶ、Podで DHCPをリッスンする手法
tomokon
0
140
Findy AI+の開発、運用におけるMCP活用事例
starfish719
0
1.3k
20251212 AI 時代的 Legacy Code 營救術 2025 WebConf
mouson
0
190
LLMで複雑な検索条件アセットから脱却する!! 生成的検索インタフェースの設計論
po3rin
4
850
Featured
See All Featured
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
1
200
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
46
4 Signs Your Business is Dying
shpigford
186
22k
Prompt Engineering for Job Search
mfonobong
0
110
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
110
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
9
1k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
180
Marketing to machines
jonoalderson
1
4.3k
Become a Pro
speakerdeck
PRO
31
5.7k
Documentation Writing (for coders)
carmenintech
77
5.2k
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