Denis Lebedev, Swift

Post on 10-May-2015

25.137 views 5 download

Tags:

Transcript of Denis Lebedev, Swift

Swift

Denis Lebedev, iOS @ Yandex

Agenda

• Introduction

• Objective-C bridging

• Good-to-know features

• “Where can I Swift?”

Swift

Chris Lattner, Swift creator

Swift

• Multi-paradigm

• Static, inferred typing

• Bridged with Objective-C

• No pointers

–Someone at WWDC Keynote

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

Swift features

• Namespacing*

• Generic classes & functions

• Named/default parameters

• Functions are first class citizens

• Optional types

Optionals

• Used in situations where value may be absent

• Alternative for obj-c nil passing

• works with any type

Optionals

- (NSInteger)indexOfObject:(id)object;

Optionals

func indexOf(object: AnyObject) -> Int?

Optionals

• Can be safely unwrapped (if/else)

• Can be force unwrapped (runtime exception if

value is missing)

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

Enumerations

enum Tree {

case Empty

case Leaf

case Node

}

Enumerations

enum Tree {

case Empty

case Leaf(Int)

case Node(Tree, Tree)

}

Enumerations

enum Tree<T> {

case Empty

case Leaf(T)

case Node(Tree, Tree)

}

Enumerations

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

Enumerations

enum Tree<T> {

case Empty

case Leaf(T)

case Node(Tree, Tree)

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

return 0

}

}

Enumerations

enum Tree<T> {

case …

func depth() -> Int {

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

return 0

}

return _depth(self)

}

}

Enumerations

enum Tree<T> {

case …

func depth() -> Int {

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

switch t {

case .Empty:

return 0

}

return _depth(self)

}

}

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)

}

}

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)

}

}

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)

}

}

Collections

• Array, Dictionary, String (contains Char)

• Collections are structs

• Implicitly bridged to Cocoa collection types

Collections

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

FilterSequenceView<S>

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

ReverseView<C>

Some of operations are lazy evaluated

Collections

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

FilterSequenceView<S>

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

ReverseView<C>

Some of operations are lazy evaluated

Built-in immutability

var b = 3

b += 1

let a = 3

a += 1 // error

Dictionary immutability

let d = ["key0": 0]

d["key"] = 3 //error

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

Array immutability

let c = [1, 2, 3]

c[0] = 3 // success

c.append(5) // fail

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

Extensions

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

• structures code

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

}

What Swift is missing

• Preprocessor

• Exceptions

• Access control *

• KVO, KVC

• Compiler attributes (platforms, deprecations, etc.)

• performSelector: is unavailable

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

Objective-C bridging

• NSArray < - > Array

• NSDictionary < - > Dictionary

• NSNumber - > Int, Double, Float

Objective-C bridging

@objc class Foo {

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

}

Objective-C bridging

@objc(objc_Foo)

class Foo {

@objc(initWithBar:)

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

}

Objective-C bridging

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

Objective-C bridging

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

CGPoint

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

Objective-C bridging

• All object types are mapped as implicitly

unwrapped optionals (T!)

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

Swift internals

• Swift objects are Obj-c objects

• Implicit root class ‘SwiftObject’

• Ivars type encoding is stored separately

• Method’s vtable

• Name mangling

Name mangling

class Foo {

func bar() -> Bool {

return false

}

}

_TFC9test3Foo3barfS0_FT_Sb

Swift keeps function metadata encoded in function symbols

Performance

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

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

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

Performance

• Swift is still in beta

• Unoptimized calls of retain/release in loops

Cross-platform code

#if os(iOS)

typealias View = UView

#else

typealias View = NSView

#endif

class MyControl : View {

}

Pattern matching

let point = (0, 1)

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

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

println("I")

}

...

Pattern matching

let point = (0, 1)

switch point {

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

println("I")

}

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.")

}

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

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.")

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.")

Implicit type conversion

struct Box<T> {

let _value : T

init (_ value: T) {

_value = value

}

}

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

Implicit type conversion

func foo(i: Int) {…}

foo(boxedInt)

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

Implicit type conversion

extension Box {

@conversion func __conversion() -> T {

return value

}

}

foo(boxedInt) //success

Implicit type conversion

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

• allows toll-free-bridging with Cocoa types

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

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;

Scripting and REPL

• xcrun swift - launches REPL

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

Where can I swift?

• BDD Testing framework: Quick

• Reactive programming: RXSwift

• Model mapping: Crust

• Handy JSON processing: SwiftyJSON

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