to swift 2...and beyond!
TRANSCRIPT
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
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-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-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 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() {
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) }
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
let tuple1 = (1, "Two")
let tuple2 = (1, "Two")
tuple1.0 == tuple2.0 && tuple1.1 == tuple2.1 // true
...and Beyond: Swift 2.2
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 3.0func contains(_: CGPoint) -> Bool
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) { // ... }
textView.text.trimming(.whitespaceAndNewlines)
...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)