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
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
AI巻き込み型コードレビューのススメ
nealle
1
290
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
450
MDN Web Docs に日本語翻訳でコントリビュート
ohmori_yusuke
0
650
副作用をどこに置くか問題:オブジェクト指向で整理する設計判断ツリー
koxya
1
610
Grafana:建立系統全知視角的捷徑
blueswen
0
330
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
5
1k
Apache Iceberg V3 and migration to V3
tomtanaka
0
160
15年続くIoTサービスのSREエンジニアが挑む分散トレーシング導入
melonps
2
200
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
AI & Enginnering
codelynx
0
110
Amazon Bedrockを活用したRAGの品質管理パイプライン構築
tosuri13
4
710
Featured
See All Featured
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
640
Automating Front-end Workflow
addyosmani
1371
200k
SEO for Brand Visibility & Recognition
aleyda
0
4.2k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
190
Claude Code のすすめ
schroneko
67
210k
Docker and Python
trallard
47
3.7k
AI: The stuff that nobody shows you
jnunemaker
PRO
2
260
Skip the Path - Find Your Career Trail
mkilby
0
56
The Pragmatic Product Professional
lauravandoore
37
7.1k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
60
42k
Site-Speed That Sticks
csswizardry
13
1.1k
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