to swift 2...and beyond!

161
... and Beyond! To Swift 2

Upload: scott-gardner

Post on 11-Apr-2017

19.525 views

Category:

Software


1 download

TRANSCRIPT

... and Beyond!To Swift 2

About me• iOS developer since 2010 • Swift since day 1 • Transitioning to Swift • RayWenderlich.com • CocoaConf • Wash U • Swift 2 Essential Training on lynda.com • Principal iOS Architect at Care Otter

WWDC 2014

without the CObjective-C

without the GCCObjective-C

Chris Lattner

GCC

LLVM

Swift

WWDC 2015

Open Sourcing Swift

Swift Open Source

swift.org

Swift Open Source

swift.org

Swift

Who are you?• Doing iOS development?

• For more than 1 year?

• Swift?

• Swift 2?

What I’ll cover• To Swift from Objective-C

• To Swift 2

• ...and Beyond!• What’s coming in Swift 2.2 and 3.0

To Swift from Objective-C

Optionals

ClassesFunctions &

ClosuresEnumerations

ReferenceTypes

ValueTypes

Structures

IntegersFloating-Points

BooleansCharactersStringsArrays

DictionariesTuples

To Swift from Objective-C

Value types are passed by copy

ValueTypex = y = xValue

TypeValue

Type copy

To Swift from Objective-C

Reference types are passed by reference

x = y = xReferenceType

ReferenceType

To Swift from Objective-C

Objective-C Swift

To Swift from Objective-CNSString *greeting = @"Hello"; let greeting = "Hello"

To Swift from Objective-CNSString *greeting = @"Hello"; let greeting: String = "Hello"

No Semicolons

To Swift from Objective-CNSMutableString *greeting = @"Hello"; var greeting = "Hello"

To Swift from Objective-CNSMutableString *greeting = var greeting = "Hello"

greeting += ", world!"[greeting appendString:@", world!"];

[@"Hello" mutableCopy];

To Swift from Objective-CNSMutableString *greeting = var greeting = "Hello"

[greeting appendString:@", world!"];

[@"Hello" mutableCopy];

greeting = greeting.stringByAppendingString(", world!")

To Swift from Objective-CNSMutableString *greeting = var greeting = "Hello"

greeting += ", world!"[greeting appendString:@", world!"];

[@"Hello" mutableCopy];

NSLog(@"%@", greeting); // 2016-... Hello, world! NSLog("%@", greeting) // 2016-... Hello, world!

NSLog(greeting) // 2016-... Hello, world!

print(greeting) // Hello, world!

print("Scott said: \(greeting)")

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2; // Int

// Int

let two = 2

let negativeOne = -1

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2; let two: UInt = 2

// Intlet negativeOne = -1

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2; let two = 2 as UInt

// Intlet negativeOne = -1

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2;

// Intlet negativeOne = -1

let two: UInt = 2

let one = negativeOne + twoNSInteger one = negativeOne + two; !error: ambiguous use of operator '+'

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2;

// Intlet negativeOne = -1

let two: UInt = 2

NSInteger one = negativeOne + two; let one = negativeOne + Int(two)

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2;

// Intlet negativeOne = -1

let two: UInt = 2

NSInteger one = negativeOne + two; let one = negativeOne + Int(two)

let threePointOneFour: Float = 3.14CGFloat threePointOneFour = 3.14;

let π = M_PI // Double, 3.141592653589793

let ! = "What's that smell?"

NSString *greeting = @"Hello!"; let greeting = "Hello!"

let a: Character = "a"char a = 'a';

BOOL thisMuchIs = let thisMuchIs =YES; true

id anyObject = [NSObject new]; let anyObject: AnyObject = NSObject()

let numberOne = NSNumber(integer: 1)

To Swift from Objective-CNSInteger negativeOne = -1;

NSUInteger two = 2;

// Intlet negativeOne = -1

let two: UInt = 2

NSInteger one = negativeOne + two; let one = negativeOne + Int(two)

let threePointOneFour = 3.14 // Doublelet threePointOneFour: Float = 3.14CGFloat threePointOneFour = 3.14;

let π = M_PI // Double, 3.141592653589793

let ! = "What's that smell?"

NSString *greeting = @"Hello!"; let greeting = "Hello!"

let a: Character = "a"char a = 'a';

BOOL thisMuchIs = let thisMuchIs =YES; trueNO;

id anyObject = [NSObject new]; let anyObject: AnyObject = NSObject()

let numberOne = NSNumber(integer: 1)

NSRange range = NSMakeRange(0, 5); let rangeInclusive = 0...5

let rangeExclusive = 0..<5

To Swift from Objective-CNSMutableString *greeting = var greeting = "Hello"

greeting = nilgreeting = nil;

[@"Hello" mutableCopy];

if (greeting) { // ... }

!error: nil cannot be assigned to type 'String'

To Swift from Objective-CNSMutableString *greeting =

greeting = nilgreeting = nil;

[@"Hello" mutableCopy];

if (greeting) { // ... }

var greeting: String? = "Hello"

if let greeting = greeting { // ... }

greeting?.isEmpty

greeting?.characters.first?.hashValue

var dateOfBirth: NSDate! = NSDate(timeIntervalSince1970: 20581200)

dateOfBirth.descriptionWithLocale(NSLocale. currentLocale())

print(greeting!.characters.first!)!error: unexpectedly found nil while unwrapping an Optional value

To Swift from Objective-CNSMutableString *greeting =

greeting = nil;

[@"Hello" mutableCopy];

if (greeting) { // ... }

var greeting: String? = "Hello"

if let greeting = greeting { // ... }

greeting?.isEmpty

greeting?.characters.first?.hashValue

var dateOfBirth: NSDate! = NSDate(timeIntervalSince1970: 20581200)

dateOfBirth.descriptionWithLocale(NSLocale. currentLocale())

print(greeting!.characters.first!)

//greeting = nil

To Swift from Objective-Clet letters = ["A", "B", "C"]NSArray *letters = @[@"A", @"B", @"C"];

To Swift from Objective-CNSArray *letters = @[@"A", @"B", @"C"]; let letters: [String] = ["A", "B", "C"]

To Swift from Objective-CNSArray *letters = @[@"A", @"B", @"C"]; let letters: Array<String> = ["A", "B", "C"]

To Swift from Objective-CNSDictionary *numbers = @{@1 : @"One", @2 : @"Two", @3 : @"Three"};

NSArray *letters = @[@"A", @"B", @"C"];

let numbers = [1: "One", 2: "Two", 3: "Three"]

let letters = ["A", "B", "C"]

To Swift from Objective-CNSDictionary *numbers = @{@1 : @"One", @2 : @"Two", @3 : @"Three"};

NSArray *letters = @[@"A", @"B", @"C"]; let letters = ["A", "B", "C"]

let numbers: [Int: String] = [1: "One", 2: "Two", 3: "Three"]

To Swift from Objective-CNSDictionary *numbers = @{@1 : @"One", @2 : @"Two", @3 : @"Three"};

NSArray *letters = @[@"A", @"B", @"C"]; let letters = ["A", "B", "C"]

let numbers: Dictionary<Int, String> = [1: "One", 2: "Two", 3: "Three"]

To Swift from Objective-CNSDictionary *numbers = @{@1 : @"One", @2 : @"Two", @3 : @"Three"};

NSSet *uniqueValues = [NSSet setWithArray:@[@1, @2, @3, @1]];

print(uniqueValues) // [2, 3, 1]

NSArray *letters = @[@"A", @"B", @"C"];

let uniqueValues: Set<Int> = [1, 2, 3, 1]

let letters = ["A", "B", "C"]

let numbers = [1: "One", 2: "Two", 3: "Three"]

let httpResponse: = (200, "OK")

To Swift from Objective-CNSDictionary *numbers = @{@1 : @"One", @2 : @"Two", @3 : @"Three"};

NSSet *uniqueValues = [NSSet setWithArray:@[@1, @2, @3, @1]];

print(uniqueValues) // [2, 3, 1]

NSArray *letters = @[@"A", @"B", @"C"];

let uniqueValues: Set<Int> = [1, 2, 3, 1]

let letters = ["A", "B", "C"]

let numbers = [1: "One", 2: "Two", 3: "Three"]

let httpResponse: (Int, String) = (200, "OK")

To Swift from Objective-CNSDictionary *numbers = @{@1 : @"One", @2 : @"Two", @3 : @"Three"};

NSSet *uniqueValues = [NSSet setWithArray:@[@1, @2, @3, @1]];

print(uniqueValues) // [2, 3, 1]

NSArray *letters = @[@"A", @"B", @"C"];

let uniqueValues: Set<Int> = [1, 2, 3, 1]

let letters = ["A", "B", "C"]

let numbers = [1: "One", 2: "Two", 3: "Three"]

let httpResponse: (code: Int, text: String) = (code: 200, text: "OK")

let httpResponseCode = httpResponse.code // 200

let httpResponseText = httpResponse.1 // OK

func getHttpStatus() -> (code: Int, text: String) { return (200, "OK") }

To Swift from Objective-Clet names = ["Moe", "Larry", "Curly"]

if names.count > 0 { for name in names { print(name) } }

NSArray *names = @[@"Moe", @"Larry", @"Curly"];

if (names.count > 0) { for (NSString *name in names) { NSLog(@"%@", name); } }

func printNames() { guard names.count > 0 else { return } names.forEach { print($0) } }

To Swift from Objective-CNSInteger score = arc4random_uniform(101);

switch (score) {

case 100: // ... break; default: break;

}

let score =

switch score {

default: break

}

arc4random_uniform(101)

case 99, 100: print("Top 2%") fallthrough

case 95...100: print("Great job!")

case let n where n % 2 == 0: print(n, "is even")

To Swift from Objective-CNSInteger score = arc4random_uniform(101);

switch (score) {

case 100: // ... break; default: break;

}

let score =

switch score {

default: break

}

99

// Prints "Top 2%"

// Prints "Great job!"

case 99, 100: print("Top 2%") fallthrough

case 95...100: print("Great job!")

case let n where n % 2 == 0: print(n, "is even")

To Swift from Objective-C// In prepareForSegue:sender:…

if let identifier = segue.identifier { switch (identifier, segue.destinationViewController) {

}

}

case ("ShowControls", is ControlsViewController): // ...

case ("ShowDetail", is DetailViewController): // ...

default: break

To Swift from Objective-C- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

To Swift from Objective-Cfunc addThis(this: Int, andThat that: Int) -> Int { return this + that }

- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

To Swift from Objective-Cfunc addThis(this: Int, andThat that: Int) -> Int { return this + that }

- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

+ (void)doSomething { // ... }

class func doSomething() { // ... }

To Swift from Objective-Cfunc addThis(this: Int, andThat that: Int) -> Int { return this + that }

- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

+ (void)doSomething { // ... }

static func doSomething() { // ... }

To Swift from Objective-Cfunc addThis(this: Int, andThat that: Int) -> Int { return this + that }

- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

+ (void)doSomething { // ... }

static func doSomething() { // ... }

To Swift from Objective-Cfunc addThis(this: Int, andThat that: Int) -> Int { return this + that }

- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

+ (void)doSomething { // ... }

static func doSomething() -> Void { // ... }

To Swift from Objective-Cfunc addThis(this: Int, andThat that: Int) -> Int { return this + that }

- (void)addThis:(NSInteger)this andThat:(NSInteger)that { return this + that; }

+ (void)doSomething { // ... }

static func doSomething() { // ... }

addThis(1, andThat: 2)

func addThisAndThat(this: Int, _ that: Int) -> Int { return this + that }

addThisAndThat(1, 2)

To Swift from Objective-Cclass SomeClass: NSObject {// SomeClass.h

#import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

let title: String init(title: String) { self.title = title } }

To Swift from Objective-Cclass SomeClass: NSObject {// SomeClass.h

#import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

let title: String init(title: String) { self.title = title } }

To Swift from Objective-Cclass SomeClass: NSObject {// SomeClass.h

#import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

static var aStaticValue = 1

let title: String init(title: String) { self.title = title } }

To Swift from Objective-C// SomeClass.h #import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

class SomeClass: NSObject { static var aStaticValue = 1

let title: String

init(theTitle: String) { title = theTitle } }

To Swift from Objective-C// SomeClass.h #import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

class SomeClass: NSObject { static var aStaticValue = 1

let title: String

init(title: String) { self.title = title } }

To Swift from Objective-CSomeClass *someClass = [[SomeClass alloc] initWithTitle:@"A Mighty Instance"];

To Swift from Objective-Clet someClass = SomeClass(title: "A Mighty Title")SomeClass *someClass = [SomeClass new];

someClass.title = @"A Mighty Instance";

To Swift from Objective-CSomeClass *someClass = [SomeClass new]; someClass.title = @"A Mighty Instance";

let someClass = SomeClass() error: missing argument for parameter 'title' in call

!

To Swift from Objective-C// SomeClass.h #import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

class SomeClass: NSObject { static var aStaticValue = 1

let title: String

init(title: String) { self.title = title super.init() } }

To Swift from Objective-C// SomeClass.h #import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

class SomeClass: NSObject { static var aStaticValue = 1

let title: String

init(title: String) { super.init() self.title = title } }

!

error: property 'self.title' not initialized at super.init call

To Swift from Objective-C// SomeClass.h #import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

class SomeClass: NSObject { static var aStaticValue = 1

?

}

var title: String

To Swift from Objective-Cclass SomeClass static var aStaticValue = 1 var title: String }

// SomeClass.h #import <Foundation/Foundation.h>

@interface SomeClass : NSObject

@property (copy, nonatomic) NSString *title;

- (instancetype)initWithTitle:(NSString *)title;

@end

// SomeClass.m #import "SomeClass.h"

@implementation SomeClass

- (instancetype)initWithTitle:(NSString *)title { if (self = [super init]) { self.title = title; return self; } return nil; }

@end

{

?

To Swift from Objective-C

PropertiesMethods

SubscriptsInitializers

ExtensionsAdopt Protocols

Class✓✓✓✓✓✓

Structure✓✓✓✓✓✓

Enumeration✓✓✓✓✓✓

To Swift from Objective-Cstruct Coordinate { CGFloat x; CGFloat y; CGFloat z; };

struct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat }

To Swift from Objective-Cstruct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat }

struct Coordinate { CGFloat x; CGFloat y; CGFloat z; NSString *title; };

!

error: ARC forbids Objective-C objects in struct

To Swift from Objective-Cstruct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat var title: String }

struct Coordinate { CGFloat x; CGFloat y; CGFloat z; // NSString *title; };

To Swift from Objective-C

let coordinate = Coordinate(x: 0.0, y: 0.0, z: 0.0, title: "Origin")

struct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat var title: String }

struct Coordinate { CGFloat x; CGFloat y; CGFloat z; // NSString *title; };

struct Coordinate coordinate = {10.0, 10.0, 10.0};

To Swift from Objective-C

let coordinate = Coordinate(x: 0.0, y: 0.0, z: 0.0, title: "Origin")

enum Heading: Int { case North, South, East, West }

struct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat var title: String }

struct Coordinate { CGFloat x; CGFloat y; CGFloat z; // NSString *title; };

struct Coordinate coordinate = {10.0, 10.0, 10.0};

typedef NS_ENUM(NSInteger, Heading) { HeadingNorth, HeadingEast, HeadingSouth, HeadingWest };

To Swift from Objective-C

let coordinate = Coordinate(x: 0.0, y: 0.0, z: 0.0, title: "Origin")

struct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat var title: String }

struct Coordinate { CGFloat x; CGFloat y; CGFloat z; // NSString *title; };

struct Coordinate coordinate = {10.0, 10.0, 10.0};

typedef NS_ENUM(NSInteger, Heading) { HeadingNorth, HeadingEast, HeadingSouth, HeadingWest };

enum Heading { case North, South, East, West }

To Swift from Objective-C

let coordinate = Coordinate(x: 0.0, y: 0.0, z: 0.0, title: "Origin")

let movement = Movement.North(distance: 20.0)

struct Coordinate { var x: CGFloat var y: CGFloat var z: CGFloat var title: String }

struct Coordinate { CGFloat x; CGFloat y; CGFloat z; // NSString *title; };

struct Coordinate coordinate = {10.0, 10.0, 10.0};

typedef NS_ENUM(NSInteger, Heading) { HeadingNorth, HeadingEast, HeadingSouth, HeadingWest };

enum Heading { case North, South, East, West }

enum Movement { case North(distance: Double) case South(distance: Double) case East(distance: Double) case West(distance: Double) }

To Swift from Objective-C- (NSString *)fullName { return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; }

- (void)setTitle:(NSString *)title { NSLog(@"Old title: %@", _title); _title = title; }

struct Person { let firstName: String let lastName: String

}

var fullName: String { return "\(firstName) \(lastName)" }

var title: String { didSet { print("Old title: " + oldValue) } }

To Swift from Objective-C// ViewController+UITableViewDataSource.m #import "ViewController.h"

@interface ViewController (UITableViewDataSource)

@end

// ViewController+UITableViewDataSource.m #import "ViewController+UITableViewDataSource.h"

@implementation ViewController (UITableViewDataSource)

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; }

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; // ... return cell; }

@end

extension ViewController: UITableViewDataSource { func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell")! // ... return cell } }

To Swift from Objective-C@IBDesignable class DesignableView: UIView { }

extension UIView { @IBInspectable var borderWidth: CGFloat { get { return layer.borderWidth } set { layer.borderWidth = newValue } } @IBInspectable var borderColor: UIColor? { get { return layer.borderColor != nil ? UIColor(CGColor: layer.borderColor!) : nil } set { layer.borderColor = newValue?.CGColor } } @IBInspectable var cornerRadius: CGFloat { get { return layer.cornerRadius } set { layer.masksToBounds = newValue != 0 layer.cornerRadius = newValue } } }

To Swift from Objective-CUIView.animateWithDuration(1.0, animations: { // ... }, completion: { print("Done!") })

[UIView animateWithDuration:1.0 animations:^{ // ... } completion:^(BOOL finished) { NSLog(@"Done!"); }];

(finished: Bool) in

To Swift from Objective-CUIView.animateWithDuration(1.0, animations: { // ... }, completion: { print("Done!") })

[UIView animateWithDuration:1.0 animations:^{ // ... } completion:^(BOOL finished) { NSLog(@"Done!"); }];

finished in

To Swift from Objective-CUIView.animateWithDuration(1.0, animations: { // ... }, completion: { print("Done!") })

[UIView animateWithDuration:1.0 animations:^{ // ... } completion:^(BOOL finished) { NSLog(@"Done!"); }];

UIView.animateWithDuration(1.0, animations: { // ... }) { _ in print("Done!") }

finished in

To Swift from Objective-CUIView.animateWithDuration(1.0, animations: { // ... }, completion: { print("Done!") })

[UIView animateWithDuration:1.0 animations:^{ // ... } completion:^(BOOL finished) { NSLog(@"Done!"); }];

UIView.animateWithDuration(1.0, animations: { // ... }) { _ in print("Done!") }

var fileContents = { // Some complex work return "..." }()

finished in

To Swift from Objective-Coverride func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; dispatch_queue_t queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __weak ViewController *weakSelf = self; dispatch_async(queue, ^{ __strong ViewController *strongSelf = weakSelf; if (!strongSelf) { return; } [strongSelf // ... }); }

dispatch_async(queue) { [unowned self] in self.//... } }

To Swift from Objective-Coverride func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) let queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; dispatch_queue_t queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __weak ViewController *weakSelf = self; dispatch_async(queue, ^{ __strong ViewController *strongSelf = weakSelf; if (!strongSelf) { return; } [strongSelf // ... }); }

dispatch_async(queue) { [weak self] in if let strongSelf = self { strongSelf.//... } } }

To Swift from Objective-Cprotocol HasTitle { var title: String { get set } func printTitle() }

@protocol HasTitle <NSObject>

@property (copy, nonatomic) NSString *title;

- (void)printTitle;

@end

To Swift from Objective-Cprotocol HasTitle { var title: String { get set } func printTitle() }

@protocol HasTitle <NSObject>

@property (copy, nonatomic) NSString *title;

- (void)printTitle;

@end

struct Book: HasTitle { var title: String var pages: Int func printTitle() { print("Title: \(title) (\(pages) pages)") } }

struct DVD: HasTitle { var title: String var length: Int func printTitle() { print("Title: \(title) (\(length) minutes)") } }

To Swift from Objective-C

let book = Book(title: "It", pages: 1104)

let dvd = DVD(title: "It", length: 187)

let myCollection: [HasTitle] = [book, dvd]

for item in myCollection { item.printTitle() }

// Title: It (1104 pages) // Title: It (187 minutes)

struct Book: HasTitle { var title: String var pages: Int func printTitle() { print("Title: \(title) (\(pages) pages)") } }

struct DVD: HasTitle { var title: String var length: Int func printTitle() { print("Title: \(title) (\(length) minutes)") } }

To Swift from Objective-Clet book = Book(title: "It", pages: 1104)

let dvd = DVD(title: "It", length: 187)

let myCollection: [HasTitle] = [book, dvd]

for item in myCollection { item.printTitle() }

To Swift from Objective-Clet book = Book(title: "It", pages: 1104)

let dvd = DVD(title: "It", length: 187)

let myCollection: [HasTitle] = [book, dvd]

for item in myCollection { item.printTitle() switch item { case is Book: print("has", (item as! Book).pages, "pages") case is DVD: print("is", (item as! DVD).length, "minutes") default: break } }

To Swift from Objective-Clet book = Book(title: "It", pages: 1104)

let dvd = DVD(title: "It", length: 187)

let myCollection: [HasTitle] = [book, dvd]

for item in myCollection { item.printTitle() if let book = item as? Book { print("has", book.pages, "pages") } if let dvd = item as? DVD { print("is", dvd.length, "minutes") } }

To Swift from Objective-Cstruct Array<Element> // ...

struct Dictionary<Key: Hashable, Value> // ...

struct Set<Element: Hashable> // ...

To Swift from Objective-Cstruct Array<Element> // ...

struct Dictionary<Key: Hashable, Value> // ...

struct Set<Element: Hashable> // ...

struct ItemHolder<T> { var items: [T] func randomItem() -> T { let index = Int(arc4random_uniform(UInt32(items.count))) return items[index] } }

To Swift from Objective-Clet numberHolder = ItemHolder(items: [1, 2, 3])

let objectA = SomeClass(title: "A") let objectB = SomeClass(title: "B") let objectC = SomeClass(title: "C")

let objectHolder = ItemHolder(items: [objectA, objectB, objectC])

numberHolder.randomItem() // 2

stringHolder.randomItem() // Neil

objectHolder.randomItem().title // A

func randomItemFromArray<T>(items: [T]) -> T {

let index = Int(arc4random_uniform(UInt32(items.count))) return items[index]

}

let stringHolder = ItemHolder(items: ["Neil", "Geddy", “Alex"])

To Swift from Objective-C• Access control

• Scopes• Module• File

• Levels• Public• Internal• Private

To Swift from Objective-C• Access control

• Public• Highest level of accessibility• Good for framework API• Code available throughout defining module• Available to other modules via import

To Swift from Objective-C• Access control

• Internal• Default for projects• Code available throughout defining module• Cannot be imported

To Swift from Objective-C• Access control

• Private• Default for playgrounds• Code available only in defining source file• Cannot be imported

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift from Objective-C

To Swift 2println("Hello, world!")

To Swift 2print("Hello, world!")

To Swift 2print("Hello, world!")

print(1, 2, 3, "...") // 1 2 3 ...

print(1, 2, 3, separator: "-") // 1-2-3

print(1, 2, separator: "", terminator: "")

print(3)

// 123

let stockPrices = ["AAPL": 101.42]

print("\(stockPrices["AAPL"])")

To Swift 2let someCondition = true

func doSomething() {

if someCondition { print("Success") } }

To Swift 2let someCondition = true

func doSomething() {

guard someCondition else { return } print("Success") }

To Swift 2let someCondition = true

func doSomething() {

guard someCondition else { return } print("Success") }

func getBirthdayFromDate(date: NSDate?) -> String {

guard let date = date else { return "" } return date.descriptionWithLocale(NSLocale.currentLocale())

}

To Swift 2let someCondition = true

func doSomething() {

guard someCondition else { return } print("Success") }

func getBirthdayFromDate(date: NSDate?) -> String {

defer { print("This will always print") } guard let date = date else { return nil } return date.descriptionWithLocale(NSLocale.currentLocale()) }

print(getBirthdayFromDate(nil))

// This will always print //

To Swift 2let someCondition = true

func doSomething() {

guard someCondition else { return } print("Success") }

func getBirthdayFromDate(date: NSDate?) -> String {

defer { print("This will always print") } guard let date = date else { return nil } return date.descriptionWithLocale(NSLocale.currentLocale()) }

print(getBirthdayFromDate(NSDate(timeIntervalSince1970: 20581200)))

// This will always print // Thursday, August 27, 1970 at 12:00:00 AM Central Daylight Time

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

let simulatedErrorA = true let simulatedErrorB = true

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

do {

} catch {

}

let simulatedErrorA = true let simulatedErrorB = true

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

do {

} print("Success!") try testErrorHandling()

print("Uh oh:", error) catch {

}

let simulatedErrorA = true let simulatedErrorB = true

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

do {

} print("Success!") try testErrorHandling()

catch Error.A { print("Error A occurred") }

let simulatedErrorA = true let simulatedErrorB = true

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

do {

} print("Success!") try testErrorHandling()

catch Error.A { print("Error A occurred") } catch let Error.B(code, function) { print("Code:", code, "Function:", function) }

let simulatedErrorA = true let simulatedErrorB = true

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

do {

} print("Success!") try testErrorHandling()

catch let Error.B(code, function) where code > 4 { print("Code:", code, "Function:", function) } catch { print("Uh oh!") }

catch Error.A { print("Error A occurred") }

let simulatedErrorA = true let simulatedErrorB = true

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws {

}

guard simulatedErrorA == false else { throw Error.A }

guard simulatedErrorB == false else { let code = arc4random_uniform(10) throw Error.B(code: code, function: __FUNCTION__) }

do {

} print("Success!") try testErrorHandling()

catch let Error.B(code, function) where code > 4 { print("Code:", code, "Function:", function) } catch { print("Uh oh!") }

catch Error.A { print("Error A occurred") }

try! testErrorHandling()

let simulatedErrorA = false let simulatedErrorB = false

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws -> String { guard simulatedErrorA == false else { throw Error.A } return "Success" }

do { let success = try testErrorHandling() print(success) } catch { print("Uh oh!") }

if let success = try? testErrorHandling() { // ... }

let simulatedErrorA = false let simulatedErrorB = false

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws -> String { guard simulatedErrorA == false else { throw Error.A } return "Success" }

func performActionThatMightFail() { do { try testErrorHandling() } catch { print("Uh oh!") } }

let simulatedErrorA = false let simulatedErrorB = false

To Swift 2enum Error: ErrorType { case A case B(code: UInt32, function: String) }

func testErrorHandling() throws -> String { guard simulatedErrorA == false else { throw Error.A } return "Success" }

let simulatedErrorA = false let simulatedErrorB = false

func performActionThatMightFail() throws { try testErrorHandling() }

do { try performActionThatMightFail() } catch { // ... }

To Swift 2UIView.animateWithDuration(1.0, delay: 0.0, options: .CurveEaseInOut | .Autoreverse, animations: { () -> Void in // ... }, completion: nil)

To Swift 2UIView.animateWithDuration(1.0, delay: 0.0, options: nil, animations: { () -> Void in // ... }, completion: nil)

To Swift 2UIView.animateWithDuration(1.0, delay: 0.0, options: [.CurveEaseInOut, .Autoreverse], animations: { () -> Void in // ... }, completion: nil)

To Swift 2UIView.animateWithDuration(1.0, delay: 0.0, options: [.CurveEaseInOut, .Autoreverse], animations: { () -> Void in // ... }, completion: nil)

UIView.animateWithDuration(1.0, delay: 0.0, options: [], animations: { () -> Void in // ... }, completion: nil)

To Swift 2struct OptionSet: OptionSetType {

}

static let A = OptionSet(rawValue: 1 << 0) static let B = OptionSet(rawValue: 1 << 1) static let C = OptionSet(rawValue: 1 << 2)

let rawValue: Int init(rawValue: Int) { self.rawValue = rawValue }

let options: OptionSet = [.A, .B, .C]

if options.contains(.A) { // ... }

To Swift 2struct OptionSet: OptionSetType {

}

static let A = OptionSet(rawValue: 1 << 0) static let B = OptionSet(rawValue: 1 << 1) static let C = OptionSet(rawValue: 1 << 2)

let rawValue: Int init(rawValue: Int) { self.rawValue = rawValue }

let options: OptionSet = [.A, .B, .C]

if options.contains([.A]) { // ... }

To Swift 2struct OptionSet: OptionSetType {

}

static let A = OptionSet(rawValue: 1 << 0) static let B = OptionSet(rawValue: 1 << 1) static let C = OptionSet(rawValue: 1 << 2)

let rawValue: Int init(rawValue: Int) { self.rawValue = rawValue }

let options: OptionSet = [.A, .B, .C]

if options.contains([.A, .B]) { // ... }

To Swift 2protocol Vehicular { var passengerCapacity: Int { get } }

extension Vehicular { var passengerCapacity: Int { return 4 } }

protocol Drivable { func adjustSpeedToMph(mph: Int) }

extension Drivable { func adjustSpeedToMph(mph: Int) { print("Now traveling at \(mph) mph") } }

struct Sedan: Vehicular, Drivable { }

let sedan = Sedan()

sedan.passengerCapacity // 4

sedan.adjustSpeedToMph(75) // Now traveling at 75 mph

To Swift 2extension RawRepresentable where RawValue: IntegerType {

}

public protocol RawRepresentable {

typealias RawValue

public init?(rawValue: Self.RawValue)

public var rawValue: Self.RawValue { get }

}

To Swift 2extension RawRepresentable where RawValue: IntegerType {

}

func next() -> Self? { return Self(rawValue: self.rawValue + 1) } func previous() -> Self? { return Self(rawValue: self.rawValue - 1) }

To Swift 2extension RawRepresentable where RawValue: IntegerType {

}

func next() -> Self? { return Self(rawValue: self.rawValue + 1) } func previous() -> Self? { return Self(rawValue: self.rawValue - 1) }

enum Number: UInt { case One = 1, Two, Three, Four, Five }

let threeAfterTwo = Number(rawValue: 2)?.next()?.next()?.next() // Five

...and Beyond

let tuple1 = (1, "Two")

let tuple2 = (1, "Two")

tuple1.0 == tuple2.0 && tuple1.1 == tuple2.1 // true

...and Beyond: Swift 2.2

let tuple1 = (1, "Two")

let tuple2 = (1, "Two")

...and Beyond: Swift 2.2

tuple1 == tuple2 // true

func doSomethingWith(int: Int) { // ... }

func doSomethingWith(string: String) { // ... }

...and Beyond: Swift 2.2

let doer = doSomethingWith!note: found this candidate func doSomethingWith(int: Int) { ^ note: found this candidate func doSomethingWith(string: String) { ^

func doSomethingWith(int: Int) { // ... }

func doSomethingWith(string: String) { // ... }

...and Beyond: Swift 2.2

let intDoer = doSomethingWith(_: Int)

let stringDoer = doSomethingWith(_: String)

...and Beyond: Swift 2.2

...and Beyond: Swift 2.2

...and Beyond: Swift 3.0func contains(_: CGPoint) -> Bool

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) { // ... }

textView.text.trimming(.whitespaceAndNewlines)

...and Beyond: Swift 3.0for var i = 0; i < 10; i++ {

print(i)}

...and Beyond: Swift 3.0func addLineItem(product: String, price: Double)(quantity: Int) -> String {

// ...}

...and Beyond: Swift 3.0func scaleScore(var score: Double) {

score *= 1.1print(score)

}

scaleScore(studentScore) // 83.6

studentScore // 76.0

var studentScore = 76.0

...and Beyond: Swift 3.0var studentScore = 76.0

func scaleScore(inout score: Double) { score *= 1.1 }

scaleScore(&studentScore)

studentScore // 83.6

...and Beyond: Swift 3.0var studentScore = 76.0

func scaleScore(inout score: Double) { score *= 1.1 }

scaleScore(&studentScore)

studentScore // 83.6

if var someValue = someValue {someValue = "Cadabra"

}

var someValue: String? = "Abra"

...and Beyond: Swift 3.0var studentScore = 76.0

func scaleScore(inout score: Double) { score *= 1.1 }

scaleScore(&studentScore)

studentScore // 83.6

var someValue: String? = "Abra"

if let someValue = someValue { // ... }

...and Beyond: Swift 3.0NSNotificationCenter.defaultCenter().addObserver(self, selector: name: "SomethingDidChangeNotification", object: nil)

"somethingDidChangeNotification:",

...and Beyond: Swift 3.0NSNotificationCenter.defaultCenter().addObserver(self, selector: name: "SomethingDidChangeNotification", object: nil)

let selector = Selector(ViewController.handleSomethingDidChangeNotification(_:))

selector,

Resources• swift.org• github.com/apple/swift-evolution• swiftdoc.org• bit.ly/SwiftEssentialTraining

(case sensitive)• bit.ly/SwiftGuide

(case sensitive)

Thank you!Scott Gardner @scotteg scotteg.com careotter.com