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
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時代のキャリアプラン「技術の引力」からの脱出と「問い」へのいざない / tech-gravity
minodriven
21
7.2k
生成AIを使ったコードレビューで定性的に品質カバー
chiilog
1
270
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
Architectural Extensions
denyspoltorak
0
290
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
370
IFSによる形状設計/デモシーンの魅力 @ 慶應大学SFC
gam0022
1
300
CSC307 Lecture 07
javiergs
PRO
0
550
CSC307 Lecture 04
javiergs
PRO
0
660
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
190
humanlayerのブログから学ぶ、良いCLAUDE.mdの書き方
tsukamoto1783
0
190
フロントエンド開発の勘所 -複数事業を経験して見えた判断軸の違い-
heimusu
7
2.8k
Data-Centric Kaggle
isax1015
2
770
Featured
See All Featured
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
3.6k
How to make the Groovebox
asonas
2
1.9k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
240
Testing 201, or: Great Expectations
jmmastey
46
8k
The Cost Of JavaScript in 2023
addyosmani
55
9.5k
Faster Mobile Websites
deanohume
310
31k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Visualization
eitanlees
150
17k
Paper Plane (Part 1)
katiecoart
PRO
0
4.2k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
110
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
200
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
450
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