Skip to content

Instantly share code, notes, and snippets.

@alexpaul
Created May 20, 2021 18:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexpaul/78af5df7ab01340c1c44fea860348c79 to your computer and use it in GitHub Desktop.
Save alexpaul/78af5df7ab01340c1c44fea860348c79 to your computer and use it in GitHub Desktop.
Swift Language Primer

Swift Language Primer

Types and Variables

Swift is a compiled, strongly-typed language. The compiler uses type inference to identify the type of an object, or you can explicitly use type annotation.

Type Inference

var favoritePeanut = "Charlie Brown" // String
var theAnswer = 42 // Int
var singleFare = 2.75 // Double (Double for "double precision" Float)
var unicodePersonInChinese = "\u{4EBA}"  //String

Type Annotation

var myIntArray: [Int] = [1,2,3,4]
var myHashmapMappingStringToInt: [String: Int] = ["c": 3, "b": 2]

Constants

Swift can use let to declare immutable constants. Attempting to mutate a let constant will give a compile-time error

let pi = Double.pi
pi = 3 // Compile-time error

Conditionals

if, else, else if

Swift conditionals do not require () syntax. If an if condition is not met, the next else if block will run. If no if or else if blocks run, an else block will run. Conditionals are not required to have else if or else blocks.

let temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}
// Prints "It's really warm. Don't forget to wear sunscreen."

Ternary Operator

The Ternary Operator gives us a shorthand way of writing an if/else construct. Its syntax is a ? b : c and is read, "if a then b, otherwise c". In this case a would be a boolean expression, and b and c can be of any type but must be the same type.

let temperatureInFahrenheit = 60
let message = temperatureInFahrenheit <= 32 ? "cold" : "warm"
print(message) // prints "warm"

Iteration

Swift no longer supports C-style (for i = 0; i < 10; i++) loops. Instead, the main method of iteration is using a for in loop.

Ranges

for in loops can operate over a range that's either open or closed.

Closed Range

for i in 0..<10 {
    print(i)
}
// Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

Open Range

for i in 0...10 {
    print(i)
}
// Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Collections

Swift can also iterate over any struct or class that implements the Collection protocol.

Array

for str in ["hi", "there", "this", "is", "an", "array"] {
  print(str)
}

Dictionary (Hash Map)

for (key, value) in ["a": 1, "b": 2, "c":3] {
  print("The key is \(key) and the value is \(value)")
}

String

Strings are Collections of Characters.

for char in "this string can be iterated over" {
  print("\(char) is the character being used in the current iteration")
}

Structs and Classes

Structs

struct User {
    let name: String
    var isLoggedIn: Bool
}

var userOne = User(name: "Adam", isLoggedIn: false)
userOne.isLoggedIn = true // Changes isLoggedIn to true
userOne.name = "Beth" //Compile error because name is a let constant

Classes

class Counter {
    var count = 0

    func increment() {
        count += 1
    }
    func increment(by amount: Int) {
        count += amount
    }
    func reset() {
        count = 0
    }
}
let myCounter = Counter()
// the initial counter value is 0
myCounter.increment()
// the counter's value is now 1
myCounter.increment(by: 5)
// the counter's value is now 6
myCounter.reset()
// the counter's value is now 0

Type Methods

let radius = 5.0
let pi = Double.pi
let circleArea = pi * radius * radius
class SomeClass {
    class func someTypeMethod() {
        // type method implementation goes here
    }
}

SomeClass.someTypeMethod()

Initializers

class TwoDimensionalPoint {
    var x: Double
    var y: Double
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }
}

Inheritance

class ThreeDimensionalPoint: TwoDimensionalPoint {
    var z: Double
    init(x: Double, y: Double, z: Double) {
        self.z = z
        super.init(x: x, y: y)
    }
}

Enums

An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.

https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html

enum CompassPoint: CaseIterable {
  case north
  case south
  case east
  case west
}

let move = CompassPoint.east

switch move {
case .north:
  print("moving north")
case .south:
  print("moving south")
case .east:
  print("moving east")
case .west:
  print("moving west")
}

print("there are \(CompassPoint.allCases.count) compass points")

// iterating through an enum
for point in CompassPoint.allCases {
  print(point)
}

Optionals

Swift have robust handling to work with data that may be nil. ? after a type indicates that it is an Optional. ! Force unwraps an optional.

var temperature: Double? = nil

if temperature != nil {
    print(temperature!)
} else {
    print("Thermometer has no current valid reading.")
}
// Prints "Thermometer has no current valid reading."

Only optional types can be assigned to nil.

var myInt = 4
myInt = nil // Compile-time error

Optional Binding

var temperature: Double? = nil

if let unwrappedTemperature = temperature {
    print(unwrappedTemperature)
} else {
    print("Thermometer has no current valid reading.")
}

// Prints "Thermometer has no current valid reading

Functions

func divide(_ numerator: Int, by denominator: Int) -> Int {
  guard denominator != 0 else { return nil }
  return numerator / denominator
}

let dividend = divide(5, by: 2) // 2
let otherDividend = divide(4, by: 0) // nil

The function divide takes in two arguments: numerator and denominator. numerator has an external parameter name of _, and denominator has an external parameter name of by. When invoking a function, we use the external parameter name. If no external parameter name is specified, it is the same as the internal argument name:

func double(value: x) -> Int {
   return value * 2
}

let doubledFive = double(value: 5) //doubledFive is 10

Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

https://docs.swift.org/swift-book/LanguageGuide/Closures.html

Closures in Swift are first-order types. The syntax for a closure type is as follows:

let myDoubler: (Int) -> Int = { val: Int in return val * 2 }

Swift also offers a shorthand syntax using numbers prefixed by $.

let myDoubler: (Int) -> Int = { $0 * 2 }

All of the following are equally valid in Swift:

// function on one line
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )

// The by parameter of sorted(by:) knows its type (String, String) -> Bool
// A call to the function that defines a closure can infer the type of its arguments.
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

// If  one line, "return" is inferred
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

// We can refer to arguments by numbered shorthand names so they don't need to be declared.
// This function takes two parameters. They can be found in $0 and $1
reversedNames = names.sorted(by: { $0 > $1 } )

// String overloads the > operator which works just like any function,
// Swift sees that its type, `>(_:String, _:String) -> Bool` matches what sort expects.
reversedNames = names.sorted(by: >)

// Trailing closure syntax
// When the last argument in a function is a closure, you have the option to define it outside the parentheses
reversedNames = names.sorted() { $0 > $1 }

// Trailing closure syntax omitting the parentheses
// When a closure is the only argument to a function, the parentheses can be omitted as well
reversedNames = names.sorted { $0 > $1 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment