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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
Transcript
206 slides
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
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
680
Other Decks in Programming
See All in Programming
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
420
AIが生成したコードは読むべきか?抽象化設計とコードの品質保証 / abstraction-design-and-quality
minodriven
16
9.1k
SODA - FACT BOOK(JP)
sodainc
1
40k
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
180
protojson における文字化けの扱い
kazuki1023
0
420
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
5
860
Materialが消えた日 〜真っ白なFlutterキャンバスにRenderObjectで絵を描く〜
umigishiaoi
0
160
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
4
3.9k
はじめてのPLATEAU
nokonoko1203
1
650
Crash Auto Pipelines
veronikapj
1
410
小さなアプリを作って公開するまで
onozaty
0
170
どうしても Eloquent でリポジトリパターンをやりたいんだ #phpcon_niigata / phpcon-niigata-2026
shogogg
0
180
Featured
See All Featured
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
1
300
BBQ
matthewcrist
90
10k
A Soul's Torment
seathinner
9
3.9k
Designing for Performance
lara
612
70k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Producing Creativity
orderedlist
PRO
348
41k
Technical Leadership for Architectural Decision Making
baasie
4
640
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
1
610
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
640
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Mind Mapping
helmedeiros
1
440