Denis Lebedev, Swift

60
Swift Denis Lebedev, iOS @ Yandex

Transcript of Denis Lebedev, Swift

Page 1: Denis  Lebedev, Swift

Swift

Denis Lebedev, iOS @ Yandex

Page 2: Denis  Lebedev, Swift

Agenda

• Introduction

• Objective-C bridging

• Good-to-know features

• “Where can I Swift?”

Page 3: Denis  Lebedev, Swift

Swift

Chris Lattner, Swift creator

Page 4: Denis  Lebedev, Swift

Swift

• Multi-paradigm

• Static, inferred typing

• Bridged with Objective-C

• No pointers

Page 5: Denis  Lebedev, Swift

–Someone at WWDC Keynote

It’s like “Objective-C without C.”

Page 6: Denis  Lebedev, Swift
Page 7: Denis  Lebedev, Swift

Swift features

• Namespacing*

• Generic classes & functions

• Named/default parameters

• Functions are first class citizens

• Optional types

Page 8: Denis  Lebedev, Swift

Optionals

• Used in situations where value may be absent

• Alternative for obj-c nil passing

• works with any type

Page 9: Denis  Lebedev, Swift

Optionals

- (NSInteger)indexOfObject:(id)object;

Page 10: Denis  Lebedev, Swift

Optionals

func indexOf(object: AnyObject) -> Int?

Page 11: Denis  Lebedev, Swift

Optionals

• Can be safely unwrapped (if/else)

• Can be force unwrapped (runtime exception if

value is missing)

Page 12: Denis  Lebedev, Swift

Classes, structs,

enumerations

• Classes passed by reference, structs - by value

• Using a struct has no runtime penalty

• All scalars and even Bool are structs

• Enumerations are extremely powerful

Page 13: Denis  Lebedev, Swift

Enumerations

enum Tree {

case Empty

case Leaf

case Node

}

Page 14: Denis  Lebedev, Swift

Enumerations

enum Tree {

case Empty

case Leaf(Int)

case Node(Tree, Tree)

}

Page 15: Denis  Lebedev, Swift

Enumerations

enum Tree<T> {

case Empty

case Leaf(T)

case Node(Tree, Tree)

}

Page 16: Denis  Lebedev, Swift

Enumerations

let tree: Tree<Int> = .Node(.Leaf(1), .Leaf(1))

Page 17: Denis  Lebedev, Swift

Enumerations

enum Tree<T> {

case Empty

case Leaf(T)

case Node(Tree, Tree)

func depth<T>(t: Tree<T>) -> Int {

return 0

}

}

Page 18: Denis  Lebedev, Swift

Enumerations

enum Tree<T> {

case …

func depth() -> Int {

func _depth<T>(t: Tree<T>) -> Int {

return 0

}

return _depth(self)

}

}

Page 19: Denis  Lebedev, Swift

Enumerations

enum Tree<T> {

case …

func depth() -> Int {

func _depth<T>(t: Tree<T>) -> Int {

switch t {

case .Empty:

return 0

}

return _depth(self)

}

}

Page 20: Denis  Lebedev, Swift

Enumerations enum Tree<T> {

case …

func depth() -> Int {

func _depth<T>(t: Tree<T>) -> Int {

switch t {

case .Empty:

return 0

case .Leaf(let _):

return 1

}

return _depth(self)

}

}

Page 21: Denis  Lebedev, Swift

Enumerations enum Tree<T> {

case …

func depth() -> Int {

func _depth<T>(t: Tree<T>) -> Int {

switch t {

case .Empty:

return 0

case .Leaf(let _):

return 1

case .Node(let lhs, let rhs):

return max(_depth(lhs), _depth(rhs))

}

}

return _depth(self)

}

}

Page 22: Denis  Lebedev, Swift

Enumerations enum Tree<T> {

case Empty

case Leaf(T)

case Node(Tree, Tree)

func depth() -> Int {

func _depth<T>(t: Tree<T>) -> Int {

switch t {

case .Empty:

return 0

case .Leaf(let _):

return 1

case .Node(let lhs, let rhs):

return max(_depth(lhs), _depth(rhs))

}

}

return _depth(self)

}

}

Page 23: Denis  Lebedev, Swift

Collections

• Array, Dictionary, String (contains Char)

• Collections are structs

• Implicitly bridged to Cocoa collection types

Page 24: Denis  Lebedev, Swift

Collections

func filter<S : Sequence>(…) -> Bool) ->

FilterSequenceView<S>

func reverse<C : Collection …>(source: C) ->

ReverseView<C>

Some of operations are lazy evaluated

Page 25: Denis  Lebedev, Swift

Collections

func filter<S : Sequence>(…) -> Bool) ->

FilterSequenceView<S>

func reverse<C : Collection …>(source: C) ->

ReverseView<C>

Some of operations are lazy evaluated

Page 26: Denis  Lebedev, Swift

Built-in immutability

var b = 3

b += 1

let a = 3

a += 1 // error

Page 27: Denis  Lebedev, Swift

Dictionary immutability

let d = ["key0": 0]

d["key"] = 3 //error

d.updateValue(1, forKey: "key1") //error

Page 28: Denis  Lebedev, Swift

Array immutability

let c = [1, 2, 3]

c[0] = 3 // success

c.append(5) // fail

Page 29: Denis  Lebedev, Swift

Array immutability

let c = [1, 2, 3]

c[0] = 3 // success

c.append(5) // fail

It’s a bug:

https://devforums.apple.com/message/971330#971330

Page 30: Denis  Lebedev, Swift

Extensions

• extends any named type (struct, enum, class)

• structures code

Page 31: Denis  Lebedev, Swift

Extensions struct Foo {

let value : Int

}

extension Foo : Printable {

var description : String {

get {return "Foo"}

}

}

extension Foo : Equatable {

}

func ==(lhs: Foo, rhs: Foo) -> Bool {

return lhs.value == rhs.value

}

Page 32: Denis  Lebedev, Swift

What Swift is missing

• Preprocessor

• Exceptions

• Access control *

• KVO, KVC

• Compiler attributes (platforms, deprecations, etc.)

• performSelector: is unavailable

Page 33: Denis  Lebedev, Swift

Objective-C bridging

• Call Obj-c from Swift

• Call Swift from Objc with limitations

• Call CoreFoundation types directly

• C++ is not allowed (should be wrapped in Objc)

• Subclassing Swift classes not allowed in Objc

Page 34: Denis  Lebedev, Swift

Objective-C bridging

• NSArray < - > Array

• NSDictionary < - > Dictionary

• NSNumber - > Int, Double, Float

Page 35: Denis  Lebedev, Swift

Objective-C bridging

@objc class Foo {

init (bar: String) { /*...*/ }

}

Page 36: Denis  Lebedev, Swift

Objective-C bridging

@objc(objc_Foo)

class Foo {

@objc(initWithBar:)

init (bar: String) { /*...*/ }

}

Page 37: Denis  Lebedev, Swift

Objective-C bridging

Foo *foo = [[Foo alloc] initWithBar:@"Bar"];

Page 38: Denis  Lebedev, Swift

Objective-C bridging

func convertPoint(point: CGPoint, toWindow window: UIWindow!) ->

CGPoint

- (CGPoint)convertPoint:(CGPoint)point toWindow:(UIWindow *)window

Page 39: Denis  Lebedev, Swift

Objective-C bridging

• All object types are mapped as implicitly

unwrapped optionals (T!)

• All ‘id’ types are mapped as ‘AnyObject’

Page 40: Denis  Lebedev, Swift

Swift internals

• Swift objects are Obj-c objects

• Implicit root class ‘SwiftObject’

• Ivars type encoding is stored separately

• Method’s vtable

• Name mangling

Page 41: Denis  Lebedev, Swift

Name mangling

class Foo {

func bar() -> Bool {

return false

}

}

_TFC9test3Foo3barfS0_FT_Sb

Swift keeps function metadata encoded in function symbols

Page 42: Denis  Lebedev, Swift

Performance

• 10-100 x slower than C++ (-O0)

• 10 x slower than C++ (-O3)

• 1 x as C++ (-Ofast)*

Page 43: Denis  Lebedev, Swift

Performance

• Swift is still in beta

• Unoptimized calls of retain/release in loops

Page 44: Denis  Lebedev, Swift

Cross-platform code

#if os(iOS)

typealias View = UView

#else

typealias View = NSView

#endif

class MyControl : View {

}

Page 45: Denis  Lebedev, Swift

Pattern matching

let point = (0, 1)

if point.0 >= 0 && point.0 <= 1 &&

point.1 >= 0 && point.1 <= 1 {

println("I")

}

...

Page 46: Denis  Lebedev, Swift

Pattern matching

let point = (0, 1)

switch point {

case (0...1, 0...1):

println("I")

}

Page 47: Denis  Lebedev, Swift

Pattern matching let point = (0, 1)

switch point {

case (0, 0):

println("Point is at the origin")

case (0...1, 0...1):

println("I")

case (-1...0, 0...1):

println("II")

case (-1...0, -1...0):

println("III")

case(0...1, -1...0):

println("IV")

default:

println(“I don’t know.")

}

Page 48: Denis  Lebedev, Swift

Function currying

func add(a: Int)(b: Int) -> Int {

return a + b

}

let foo = add(5)(b: 3) // 8

let add5 = add(5) // (Int) -> Int

let bar = add5(b: 3) // 8

Page 49: Denis  Lebedev, Swift

Auto closures

• Wraps function argument in explicit closure

func assert(condition:() -> Bool, message: String) {

#if DEBUG

if !condition() { println(message) }

#endif

}

assert({5 % 2 == 0}, "5 isn't an even number.")

Page 50: Denis  Lebedev, Swift

Auto closures Wraps function argument in explicit closure

func assert(condition: @auto_closure () -> Bool,

message: String) {

#if DEBUG

if !condition() { println(message) }

#endif

}

assert(5 % 2 == 0, "5 isn't an even number.")

Page 51: Denis  Lebedev, Swift

Implicit type conversion

struct Box<T> {

let _value : T

init (_ value: T) {

_value = value

}

}

let boxedInt = Box(1) //Box<Int>

Page 52: Denis  Lebedev, Swift

Implicit type conversion

func foo(i: Int) {…}

foo(boxedInt)

//error: ’Box<Int>' is not convertible to 'Int'

Page 53: Denis  Lebedev, Swift

Implicit type conversion

extension Box {

@conversion func __conversion() -> T {

return value

}

}

foo(boxedInt) //success

Page 54: Denis  Lebedev, Swift

Implicit type conversion

• allows any type to be ‘nil’ (which has NilType)

• allows toll-free-bridging with Cocoa types

Page 55: Denis  Lebedev, Swift

Reflection struct Foo {

var str = "Apple"

let int = 13

func foo() { }

}

reflect(Foo()).count // 2

reflect(Foo())[0].0 // "str"

reflect(Foo())[0].1.summary // "Apple

Page 56: Denis  Lebedev, Swift

Direct call of C functions

@asmname - allows to provide a Swift interface for C functions

@asmname("my_c_func")

func my_c_func(UInt64, CMutablePointer<UInt64>) -> CInt;

Page 57: Denis  Lebedev, Swift

Scripting and REPL

• xcrun swift - launches REPL

• xcrun -i ‘file.swift’ - executes script

Page 58: Denis  Lebedev, Swift

Where can I swift?

• BDD Testing framework: Quick

• Reactive programming: RXSwift

• Model mapping: Crust

• Handy JSON processing: SwiftyJSON

Page 60: Denis  Lebedev, Swift

Credits

• http://nondot.org/sabre/

• https://devforums.apple.com/thread/227288

• http://andelf.github.io/blog/2014/06/08/swift-implicit-type-cast/

• https://www.youtube.com/watch?v=Ii-02vhsdVk

• http://www.eswick.com/2014/06/inside-swift/

• http://article.gmane.org/gmane.comp.compilers.clang.devel/37217

• http://stackoverflow.com/questions/24101718/swift-performance-sorting-arrays

• http://www.splasmata.com/?p=2798

• https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift