Basics of Swift
- You can use Swift for a variety of programming tasks: iOS and MacOS apps are the obvious use cases, but you can also use it for pretty much anything, including backend/server workloads.
- It’s a great general-purpose progamming language for interacting with anything in the Apple ecosystem.
- Swift is a statically typed compiled language, the syntax is C-like but with a really strong type system. It’s a multi-paradigm language, meaning you can code in a variety of styles — OOP-ish to FP-ish to declaritive.
- Use Xcode to edit, run, and compile Swift code. This is the most common way to, basically, develop with swift. BUT, you don’t have to use Xcode, you can use whatever editor you want. You can also compile with command line tools, just
swift ./name-of-file.swift -o build
then run./build
. Like go or any other statically compiled lang.
Syntax
- No semicolons
let
for constantsvar
for variables- Empty values are
nil
Type coercion/implicit type conversion is impossible. You can concatenate stuff into strings, though, using a \
operator, like so:
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit.
Objects + Arrays
Swift refers to my concept of “objects” as dictionaries. Arrays and dictionaries in Swift both use square brackets []
for definition. Trailing commas are optional.
For example:
var fruits = ["strawberries", "limes", "tangerines"]
var occuptions = [
"Ken": "Beach",
"Barbie": "Unemployeed",
]
Control Flow
Here’s another snippet with some basics. Note:
?
represents a potentially nil typedef- Swift often uses variable assignments in conditional if statements. If the variable assignment is non-nil, it’s unwrapped in the block which follows. Kinda like go.
var optionalString: String? = "Hello"
print(optionalString == nil)
// Prints "false"
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
Loops are pretty much the same c-esque syntax we know and love. Only notable things:
- You can do a
repeat {...} while (condition)
syntax - You can create ranges by using
..<n
syntax. Also...
for inclusive E.g.,:
var total = 0
for i in 0..<4 {
total += i
}
print(total)
// Prints "6”
Functions
Use the func
keyword. Specify return type using ->
, named arguments are default. Funcs look like this:
func greet(person: String, day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")
To not use a named argument, you can use _
, like this:
func greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
// note: no named arg for person
greet("John", on: "Wednesday")
Like Go, functions can return tuple values/multiple values. Unlike go, these are actually named and accessible by dot notation:
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)
// Prints "120"
print(statistics.2)
// Prints "120"
Accessible by index (.2
) or named label (.sum
). Kinda wild!
Enums
Enums are actually more than just types + static values in Swift. They are almost similar to Classes in some regard.
Similar to typescript and Go’s iota
, enum values are given a value under the hood which defaults to incrementing integer values starting at 1 (if the enum has a Int
type specified, see exampe below).
Enum definitions use the case
keyword, so it looks kinda like a switch statement.
enum LogLevel: Int {
case off = 0
case all, trace, debug, info, warn, error, fatal
func description() -> String {
switch self {
case .off:
return "Logging is off"
case .all:
return "Log everything"
case .trace:
return "Trace logs"
case .debug:
return "Debug logs"
case .info:
return "INFO"
case .warn:
return "warning!"
case .error:
return "Error Logs"
case .fatal:
return "Fatal 💀"
}
}
}
let logLevel = LogLevel.all
print(logLevel.description())
This snippet uses both enum and switch case.