Slide 1

Slide 1 text

Domen Lanišnik Android Engineer @ Lyft Swift Cheatsheet for Android/Kotlin Developers droidcon London 24

Slide 2

Slide 2 text

Why Swift? • To be able to read and understand iOS code • To provide code reviews for iOS teammates • To better collaborate with iOS teammates • Kotlin Multiplatform, Flutter, other cross-platform frameworks • *Also applies to iOS developers looking at Kotlin/Android code

Slide 3

Slide 3 text

Basics

Slide 4

Slide 4 text

Variables and constants Basics let animDurationMillis: Int = 500 var clickCount = 0 val animDurationMillis: Int = 500 var clickCount = 0

Slide 5

Slide 5 text

Optionals / Nullability Basics var foundItem: String? = nil var foundItem: String? = null

Slide 6

Slide 6 text

Fallback / default value Basics - Optionals / Nullability let actualFoundItem = foundItem ?? "empty" val actualFoundItem = foundItem ?: "empty"

Slide 7

Slide 7 text

Force unwrapping Basics - Optionals / Nullability let actualFoundItem = foundItem! val actualFoundItem = foundItem!!

Slide 8

Slide 8 text

Control flow Basics if foundItem != nil { // do something } if (foundItem != null) { // do something }

Slide 9

Slide 9 text

Control flow cont. Basics let description = if delta <= 10 { "low" } else if delta >= 50 { "high" } else { "medium" }

Slide 10

Slide 10 text

For loop Basics let names = ["Alice", "Bob", "Charlie"] for name in names { print(name) } val names = listOf("Alice", "Bob", "Charlie") for (name in names) { println(name) }

Slide 11

Slide 11 text

Functions Basics func addTwoNumbers(a: Int, b: Int) -> Int { return a + b } fun addTwoNumbers(a: Int, b: Int): Int { return a + b }

Slide 12

Slide 12 text

Optional Binding

Slide 13

Slide 13 text

If let Optional Binding let fetchedUserId: String? = "user_id" if let userId = fetchedUserId { updateUser(id: userId) } else { throw Error("Missing user id") }

Slide 14

Slide 14 text

If let Optional Binding if let userId = fetchedUserId { updateUser(id: userId) } else { throw Error("Missing user id") } let fetchedUserId: String? = "user_id"

Slide 15

Slide 15 text

If let Optional Binding updateUser(id: userId) } else { throw Error("Missing user id") } if let userId = fetchedUserId { let fetchedUserId: String? = "user_id"

Slide 16

Slide 16 text

If let Optional Binding } else { throw Error("Missing user id") } if let userId = fetchedUserId { let fetchedUserId: String? = "user_id" updateUser(id: userId)

Slide 17

Slide 17 text

If let Optional Binding } else { throw Error("Missing user id") } let fetchedUserId: String? = "user_id" if let userId = fetchedUserId { updateUser(id: userId)

Slide 18

Slide 18 text

If let Optional Binding let fetchedUserId: String? = "user_id" if let fetchedUserId { // can be used as non-optional constant updateUser(id: fetchedUserId) }

Slide 19

Slide 19 text

If let Optional Binding val fetchedUserId: String? = "user_id" if (fetchedUserId != null) { updateUser(fetchedUserId) } else { throw Exception("Missing user id") }

Slide 20

Slide 20 text

If let Optional Binding fetchedUserId?.let { updateUser(it) }

Slide 21

Slide 21 text

Guard Optional Binding func isUsernameValid(username: String?) -> Bool { guard let username else { return false } return username.count > 3 }

Slide 22

Slide 22 text

func isUsernameValid(username: String?) -> Bool { return username.count > 3 } Guard Optional Binding guard let username else { return false }

Slide 23

Slide 23 text

func isUsernameValid(username: String?) -> Bool { } Guard Optional Binding guard let username else { return false } return username.count > 3

Slide 24

Slide 24 text

Guard Optional Binding fun isUsernameValid(username: String?): Boolean { if (username.isNullOrEmpty()){ return false } return username.length > 3 }

Slide 25

Slide 25 text

Guard Optional Binding fun checkUsernameValid(username: String?) = username ?.let { it.length > 3 } ?: false

Slide 26

Slide 26 text

Collections

Slide 27

Slide 27 text

Types of collections Collections Array Indexes Values 0 1 2 3 4 Alice Bob Charlie Dean Eve Set Values Alice Bob Eve Dictionary Keys Values LAX DUB LHR Los Angeles Intl. London Heathrow Dublin Airport

Slide 28

Slide 28 text

Arrays Collections var names = ["Alice", "Bob", "Charlie"] names += [“John"] for name in names { print(name) }

Slide 29

Slide 29 text

Sets Collections var favoriteNames: Set = ["Alice", "Eve", "Bob"] if !favoriteNames.contains("John") { favoriteNames.insert("John") }

Slide 30

Slide 30 text

Dictionary / Map Collections var httpErrorCodes: [Int: String] = [ 404: "Not found", 401: "Unauthorized" ] httpErrorCodes[500] = "Internal Server Error" let requestError = httpErrorCodes[400] ?? “Unknown"

Slide 31

Slide 31 text

Dictionary / Map Collections for (code, message) in httpErrorCodes { print("\(code) means \(message)") }

Slide 32

Slide 32 text

Structures and classes

Slide 33

Slide 33 text

Structures vs Classes Structures and classes • Similar when modeling data (properties and functions) • Classes are pass-by-reference • Structures are pass-by-value • O ffi cial recommendation is to use structures by default • Use classes for inheritance, Objective-C compatibility and others

Slide 34

Slide 34 text

Structures Structures and Classes struct VehicleStructure { var maxSpeed = 0 func printInfo() { print("Max speed \(maxSpeed)") } }

Slide 35

Slide 35 text

Classes Structures and Classes class VehicleClass { var maxSpeed = 0 func printInfo() { print("Max speed \(maxSpeed)") } }

Slide 36

Slide 36 text

Structures Structures and classes let car = VehicleStructure(maxSpeed: 200) car.printInfo()

Slide 37

Slide 37 text

Structures Structures and classes let car = VehicleStructure(maxSpeed: 200) car.printInfo() car.maxSpeed = 220 ❌

Slide 38

Slide 38 text

Structures Structures and classes var car = VehicleStructure(maxSpeed: 200) car.printInfo()

Slide 39

Slide 39 text

Structures Structures and classes var car = VehicleStructure(maxSpeed: 200) car.printInfo() car.maxSpeed = 220 ✅

Slide 40

Slide 40 text

Classes Structures and Classes let car = VehicleClass() car.maxSpeed = 200 car.printInfo()

Slide 41

Slide 41 text

Structures and Classes Structures and Classes class Vehicle(var maxSpeed: Int) { fun printInfo(){ println("Max speed is $maxSpeed") } } val car = Vehicle(250) car.printInfo()

Slide 42

Slide 42 text

Enums

Slide 43

Slide 43 text

Declaration Enums enum Direction { case left case up case right case down } enum Direction { case left, up, right, down }

Slide 44

Slide 44 text

Usage Enums var selectedDirection = Direction.up selectedDirection = .right

Slide 45

Slide 45 text

Checking for values Enums switch(selectedDirection){ case .left: goLeft() case .up: goForward() case .right: goRight() case .down: goBackward() }

Slide 46

Slide 46 text

Associated Values Enums enum ColorType { case rgb(Int, Int, Int) case hex(String) } var buttonColor = ColorType.rgb(0, 255, 0) buttonColor = .hex(“#00FF00")

Slide 47

Slide 47 text

Associated Values Enums switch buttonColor { case .rgb(let red, let green, let blue): print("RGB: \(red), \(green), \(blue)") case .hex(let code): print("Hex code: \(code)") }

Slide 48

Slide 48 text

Associated Values Enums switch buttonColor { case let .rgb(red, green, blue): print("RGB: \(red), \(green), \(blue)") case let .hex(code): print("Hex code: \(code)") }

Slide 49

Slide 49 text

Declaration and usage Enums enum class Direction { LEFT, UP, RIGHT, DOWN } var selectedDirection = Direction.UP when(selectedDirection){ Direction.LEFT -> goLeft() Direction.UP -> goForward() Direction.RIGHT -> goRight() Direction.DOWN -> goBackward() }

Slide 50

Slide 50 text

Associated values Enums sealed class ColorType { data class Rgb( val red: Int, val green: Int, val blue: Int ) : ColorType() data class Hex( val hex: String ) : ColorType() }

Slide 51

Slide 51 text

Extensions

Slide 52

Slide 52 text

Extensions Extensions extension String { func doubled() -> String { return self + self } } let doubledStr = "Swift".doubled() print(doubledStr) // prints "SwiftSwift"

Slide 53

Slide 53 text

Extensions Extensions fun String.doubled(): String { return this + this } val doubledStr = "Kotlin".doubled() println(doubledStr) // prints "KotlinKotlin"

Slide 54

Slide 54 text

Protocols

Slide 55

Slide 55 text

What is a protocol? Protocols • Set of properties, methods, and other requirements that a class, structure, or enumeration can adopt by providing actual implementation of those requirements • Can have readable or writable properties • Support inheritance, composition, associated types, generics and more

Slide 56

Slide 56 text

Example Protocols protocol RequestError { var errorCode: Int { get } var isRecoverable: Bool { get set} } protocol PrintableError { func buildErrorMessage() -> String }

Slide 57

Slide 57 text

Adoption Protocols struct ConnectionError: RequestError, PrintableError { var errorCode: Int var isRecoverable: Bool func buildErrorMessage() -> String { return "Local connection error" } } let error = ConnectionError(errorCode: 404, isRecoverable: true)

Slide 58

Slide 58 text

Adoption Protocols func onRequestError(error: RequestError) { if let printableError = error as? PrintableError { print(printableError.buildErrorMessage()) } print("Is recoverable: \(error.isRecoverable)") }

Slide 59

Slide 59 text

Kotlin Protocols interface RequestError { val errorCode: Int var isRecoverable: Boolean } interface PrintableError { fun buildErrorMessage(): String }

Slide 60

Slide 60 text

Kotlin Protocols class ConnectionError( override val errorCode: Int, override var isRecoverable: Boolean ) : RequestError, PrintableError { override fun buildErrorMessage(): String { return "Local connection error" } } val error = ConnectionError(errorCode = 404, isRecoverable = true)

Slide 61

Slide 61 text

Closures

Slide 62

Slide 62 text

Closures Closures func someFunctionThatTakesAClosure(closure: () -> Void) { // function body goes here } someFunctionThatTakesAClosure() { // trailing closure's body goes here }

Slide 63

Slide 63 text

Concurrency

Slide 64

Slide 64 text

Overview Concurrency • Swift has built-in support for writing asynchronous code in a structured way • Asynchronous code can be suspended and resumed later • Asynchronous function is a special kind of function that can be suspended while it’s partway through execution

Slide 65

Slide 65 text

Example Concurrency func fetchUser(id: Int) async -> User { return // async network request } let user = await fetchUser(id: 1)

Slide 66

Slide 66 text

Kotlin Concurrency suspend fun fetchUser(id: Int): User { return // network request } coroutineScope.launch { val user = fetchUser(1) }

Slide 67

Slide 67 text

Example Concurrency async let firstUser = fetchUser(id: 1) async let secondUser = fetchUser(id: 2) let users = await [firstUser, secondUser]

Slide 68

Slide 68 text

Kotlin Concurrency val users = listOf( async { fetchUser(1) }, async { fetchUser(2) } ).awaitAll()

Slide 69

Slide 69 text

Summary • Swift syntax is quite similar to Kotlin • Mental mapping from Swift to Kotlin • Helps with understanding code, code reviews, tech speci fi cations • Helps with cross-platform (SwiftUI)

Slide 70

Slide 70 text

Thank you! LinkedIn Twitter / X droidcon London 24 Swift Cheatsheet for
 Android/Kotlin Developers