Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Daniel Steinberg: The Open World of Swift 3
Search
Realm
April 25, 2016
Programming
25k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Daniel Steinberg: The Open World of Swift 3
Realm
April 25, 2016
More Decks by Realm
See All by Realm
WWDC 2017 Review
realm
0
2.2k
Xcode shortcuts
realm
0
4.8k
Self Branding with GitHub
realm
0
4.4k
Realm Mobile Platform overview and demo
realm
0
2.1k
Realm advanced topics and demo
realm
0
2.1k
Realm introduction Seoul meetup 10
realm
0
2.2k
Stuart Hall: How I got 2.3 Million App Downloads
realm
0
2k
James Majors: What the Swiftly Func?
realm
1
4.3k
Simina Pasat: Continuous everything for iOS apps
realm
0
670
Other Decks in Programming
See All in Programming
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
290
難しいけど、読めた。- OSSの入口に立った話。
sts11142
0
130
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
1
2.1k
SREの越境 / SRE Collaboration
y0hgi
2
290
App Intentsのビルドプロセスを支える技術
kntkymt
0
490
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
370
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
300
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
600
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
320
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
330
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
590
The Rails Doctrine Decade
koic
2
460
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
The SEO identity crisis: Don't let AI make you average
varn
0
570
WENDY [Excerpt]
tessaabrams
14
40k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Making Projects Easy
brettharned
120
6.8k
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.1k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
Transcript
The Open World of Swift 3 AppBuilders 2016 Daniel H
Steinberg @dimsumthinking
Swift
Open
Open?
Open!
Future
Future?
Future!
What can we see?
0025 - Scoped Access Levels
public internal private
public internal private
public internal private
public internal private
public internal fileprivate
public internal fileprivate private
class MyClass { private var myProperty = "Hello" private func
myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
class MyClass { private var myProperty = "Hello" private func
myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
class MyClass { private var myProperty = "Hello" private func
myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
class MyClass { private var myProperty = "Hello" private func
myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
class MyClass { private var myProperty = "Hello" private func
myPrivateMethod() { print(myProperty) } fileprivate func myFilePrivateMethod(numberOfTimes times: Int) { for _ in 1 ... times { myPrivateMethod() } } } extension MyClass { func myExtensionMethod(numberOfTimes times: Int) { myInternalMethod(numberOfTimes: times) } }
public internal fileprivate private
0004 - Remove ++ and —
while count < upperLimit { print( myArray[count++]) }
while count < upperLimit { print( myArray[count++]) }
while count < upperLimit { print( myArray[count]) count += 1
}
0007 - Remove C Style for loops with conditions and
incrementors
for (int i = 0; i < array.count; i++)
for (int i = 0; i < array.count; i++)
0053 - Remove explicit use of let from Function Parameters
func double(input: Int) -> Int { // ... }
func double(let input: Int) -> Int { // ... }
func double(let input: Int) -> Int { // ... }
0003 - Remove var from Function Parameters
func double(input: Int) -> Int { input = input *
2 return input }
func double(var input: Int) -> Int { input = input
* 2 return input }
func double(var input: Int) -> Int { input = input
* 2 return input }
func double(input: Int) -> Int { var localInput = input
localInput = localInput * 2 return localInput }
func double(input: Int) -> Int { var localInput = input
localInput = localInput * 2 return localInput }
func double(input: Int) -> Int { var input = input
input = input * 2 return input } Name Shadowing
func double(input: Int) -> Int { var input = input
input = input * 2 return input }
0031 - Adjusting inout Declarations for Type Decoration
func double(input: Int) { input = input * 2 }
func double(inout input: Int) { input = input * 2
}
func double(inout input: Int) { input = input * 2
}
func double(input: inout Int) { input = input * 2
}
0053 - Limiting inout capture to @noescape context
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func noEscape(@noescape f: () -> ()) {} func example(inout x:
Int) { noEscape { _ = x } }
func noEscape(@noescape f: () -> ()) {} func example(inout x:
Int) { noEscape { _ = x } } safe because @noescape => closure can't be called after function returns
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape { _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape {[x] in _ = x } }
func escape(f: () -> ()) {} func example(inout x: Int)
{ escape {[x] in _ = x } } [x] is a capture list a constant is initialized to have the value of x
0049 - Move @noescape and @autoclosure to be type attributes
func noEscape(@noescape f: () -> ()) {}
func noEscape(f: @noescape () -> ()) {}
func noEscape(f: @autoclosure () -> ()) {}
0002 - Remove currying func declaration syntax
0002 - Remove currying func declaration syntax
0002 - Remove currying func declaration syntax
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8) 7 * y
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8) 7 * 8
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int)(y: Int) -> Int { return {(y: Int)
-> Int in return x * y } } curried(7)(8)
func curried(x: Int) -> (y: Int) -> Int { return
{(y: Int) -> Int in return x * y } } curried(7)(8)
func curried(x: Int) -> (y: Int) -> Int { return
{(y: Int) -> Int in return x * y } } curried(7)(8)
func curried(x: Int) -> (y: Int) -> Int { return
{(y: Int) -> Int in return x * y } } curried(7)(8)
func curried(x: Int) -> (y: Int) -> Int { return
{(y: Int) -> Int in return x * y } } curried(7)(8)
func curried(x: Int) -> (y: Int) -> Int { return
{(y: Int) -> Int in return x * y } } curried(7)(8)
Testing
Playgrounds
Package Manager
Objective-C
0022 - Referencing the Obj-C selector of a method
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: "callbackMethod", name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(with notification: NSNotification){} func
setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(){} func callbackMethod(with notification:
NSNotification){} func setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(){} func callbackMethod(with notification:
NSNotification){} func setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
class MyClass : NSObject { func callbackMethod(){} func callbackMethod(with notification:
NSNotification){} func setNotification() { let center = NSNotificationCenter.defaultCenter() center .addObserver(self, selector: #selector(MyClass.callbackMethod(with:)), name: NSApplicationWillResignActiveNotification, object: NSApplication.sharedApplication()) } }
0033 - Import Obj-C constants as Swift types
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;
HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass; HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;
HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass; HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;
enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case
Height case BodyMass case LeanBodyMass }
enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case
Height case BodyMass case LeanBodyMass }
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;
HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight; HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass; HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;
enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case
Height case BodyMass case LeanBodyMass }
enum HKQuantityTypeIdentifier : String { case BodyMassIndex case BodyFatPercentage case
Height case BodyMass case LeanBodyMass }
0005 - Better translation of Obj-C APIs into Swift
let color = NSColor.blueColor()
let color = NSColor.blueColor()
let color = NSColor.blueColor() Prune redundant type names
let color = NSColor.blue()
rootViewController .presentViewController(alert, animated: true, completion: nil)
rootViewController .presentViewController(alert, animated: true, completion: nil) Add default arguments
rootViewController .presentViewController(alert, animated: true, completion: nil) Nullable trailing closures default
= nil
rootViewController .presentViewController(alert, animated: true)
rootViewController .presentViewController(alert, animated: true) Shouldn't animated default = true
rootViewController.presentViewController(alert)
rootViewController.presentViewController(alert) Prune redundant type names
rootViewController.present(alert)
var empty: Bool
var empty: Bool Prepend "is" to Bools
var isEmpty: Bool
addLineToPoint(myPoint)
addLineToPoint(myPoint) func addLineToPoint(_: CGPoint)
addLineToPoint(myPoint) func addLineToPoint(_: CGPoint) Add first argument labels
addLineToPoint(myPoint) func addLineToPoint(_: CGPoint) Add first argument labels
addLine(to: myPoint) func addLine(to point: CGPoint) Add first argument labels
addLine(to: myPoint) func addLine(to point: CGPoint) Add first argument labels
Add first argument labels
Add first argument labels
var URLHandler
var URLHandler Lower case imported types
var urlHandler Lower case imported types
enum Currency { case Dollars case Euros case Pounds case
Yen } Lower case imported types
enum Currency { case Dollars case Euros case Pounds case
Yen } Lower case imported types
enum Currency { case dollars case euros case pounds case
yen } Lower case imported types
0036 - Requiring Leading Dot Prefixes for Enum Instance Member
Implementations
enum Currency { case dollars case euros case pounds case
yen var symbol: String { switch self { case dollars: return "$" default: return "I don't know" } } }
enum Currency { case dollars case euros case pounds case
yen var symbol: String { switch self { case .dollars: return "$" default: return "I don't know" } } }
enum Currency { case dollars case euros case pounds case
yen var symbol: String { switch self { case dollars: return "$" default: return "I don't know" } } }
enum Currency { case dollars case euros case pounds case
yen var symbol: String { switch self { case .dollars: return "$" default: return "I don't know" } } }
enum Currency { case dollars case euros case pounds case
yen var symbol: String { switch self { case .dollars: return "$" default: return "I don't know" } } }
0043 - Declare variables in 'case' labels with multiple patterns
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
enum MyEnum { case case1(Int,Float) case case2(Float,Int) } switch value
{ case let .case1(x, 2), let .case2(2, x): print(x) case .case1, .case2: break }
0001 - Allow (most) keywords as argument labels
calculateRevenue(for sales: Int, in currency: Currency)
calculateRevenue(for sales: Int, in currency: Currency)
calculateRevenue(for numberOfCopies, in .dollars)
0009 - Require self for accessing instance members
struct Friend { let name: String let location: String func
nameBadge() { print("I'm", name, "from", location) } }
struct Friend { let name: String let location: String func
nameBadge() { print("I'm", name, "from", location) } }
struct Friend { let name: String let location: String func
nameBadge() { print("I'm", name, "from", location) } }
struct Friend { let name: String let location: String func
nameBadge() { print("I'm", self.name, "from", self.location) } }
struct Friend { let name: String let location: String func
nameBadge() { print("I'm", self.name, "from", self.location) } } Require self for accessing instance members REJECTED
0011 - Replace typealias keyword with associatedtype for associated type
declarations
0011 - Replace typealias keyword with associatedtype for associated type
declarations
protocol Prot { typealias Container : SequenceType } extension Prot
{ typealias Element = Container.Generator.Element }
protocol Prot { typealias Container : SequenceType } extension Prot
{ typealias Element = Container.Generator.Element }
protocol Prot { associatedtype Container : SequenceType } extension Prot
{ typealias Element = Container.Generator.Element }
0046 Establish consistent label behavior across all parameters including first
labels
func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,
delta: 3)
func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,
delta: 3)
func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,
delta: 3)
func increase(ourNumber: Int, delta: Int) -> Int { } increase(6,
delta: 3)
func increase(ourNumber: Int, delta: Int) -> Int { } increase(ourNumber:
6, delta: 3)
func increase(_ ourNumber: Int, delta: Int) -> Int { }
increase(6, delta: 3)
0023 - Swift API Guidelines
Swift API Design Guidelines
myArray.sort()
sort() sorted()
sortInPlace() sort()
sort() sorted()
sort() sorted() Name functions and methods according to their side-effects
x.distance(to: y) i.successor() Those without side-effects should read as noun
phrases
x.sort() x.append(y) Those with side-effects should read as imperative noun
phrases
sort() sorted()/sorting() Use the “ed/ing” rule to name the nonmutating
counterpart of a mutating method
Prefer methods to free functions
Prefer methods to free functions Protocol Extensions in Swift 2
Prefer methods to free functions Protocol Extensions in Swift 2
Except …
min(x, y, z) When there's no obvious self
print(x) When the function is an unconstrained generic
sin(x) When the function is part of the established domain
notation
Methods can share a base name
Methods can share a base name Good when they do
analogous things
Methods can share a base name Not good (tableView!) when
they don't
Choose good parameter names
func move(from startingIndex: Int, to endingIndex: Int) Choose good parameter
names
Take advantage of default values
Take advantage of default values func hello(name: String = "World")
Take advantage of default values init(name: String, hometown: String? =
nil)
Prefer to locate parameters with defaults at the end init(name:
String, hometown: String? = nil)
External Argument Labels func move(from startingIndex: Int, to endingIndex: Int)
move(from: here to: there)
Argument Labels Exceptions
min(number1, number2) Omit labels when arguments can't be distinguished
Double(someInt) Omit labels in full width inits
Double(_ anInt: someInt) Omit labels in full width inits
func move(from startingIndex: Int, to endingIndex: Int) When the preposition
applies to the whole
func moveTo(x: Int, y: Int) When the preposition applies to
the whole
x.removeBoxes(having Length: 12) When the preposition applies to the whole
None
The Open World of Swift 3 AppBuilders 2016 Daniel H
Steinberg @dimsumthinking