I recently picked up Swift. This article is about some of the things in Swift that I thought were cool. I will probably update this as I come upon more cool stuff, which is bound to happen as I'm still starting out.
Swift is statically typed. It uses automatic reference counting for memory management releasing objects when there are no references to it.
This is a list of things I noticed were cool or unique or interesting. Here, we go:
let scoreDecoration = if teamScore > 10 {
"🎉"
} else {
""
}
In many languages, often other types are automatically converted to booleans when used in conditional contexts. This is prone to logical errors.
var fruits = ["strawberries", "limes", "tangerines"]
fruits[1] = "grapes"
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
Kinda nice.
Yes, case is an expression meaning you can use it for pattern matching with if
or for
too!
Like:
for case let (x, y) in points where x == y || x == -y {
print("Found (\(x), \(y)) along a line through the origin")
}
Super useful when you add a value in an enum, and the compiler will give you errors to indicate where else you need to make updates.
Implicit fallthrough is really just annoying, I would prefer either using compound cases, or a separate function.
Swift does allow explicit fallthough though.
Specifying case (let x, 0)
for a switch with a tuple, will bind the first element of the tuple to x
You can unwrap enums and tuples based on conditions - really powerful and nicer syntax which encourages less errors.
...with enums, tuples, compound cases, ranges, where
to check additional conditions
Convenient working with multiple loops. Saves adding a flag manually.
// if the person["name"] is nil, then the function would exit at this point
// after executing the else block
guard let name = person["name"] else {
return
}
Readability gang.
You can specify your clean up code near your initialization with defer blocks
This was unique and I've never seen this syntax sugar anywhere else besides Swift.
So, if you have a closure as your last argument of a function or a method call then you may omit a whole bunch of stuff. This makes the code look kinda nice, especially in case of chained methods.
Button {
if let name = names.randomElement() {
pickedName = name
if shouldRemovePickedName {
names.removeAll { name in
name == pickedName
}
}
} else {
pickedName = ""
}
} label: {
Text("Pick Random Name")
.padding(.vertical, 8)
.padding(.horizontal, 16)
}
.buttonStyle(.borderedProminent)
.font(.title2)
The above code specifies the action of the button click i.e the first closure that's the labelless argument of the button, then the label of the button is specified as another closure.
It makes a lot of sense for enums to have associated types.
This is what allows powerful pattern matching with enums.
Reduces boilerplate. This allows you to specify initializer of a property
but the code isn't executed till the property is accessed.
I wish the property was allowed to be constant too tho instead of var
. Kinda defeats the purpose of this in a way. If it's not for const, it just feels like a convenience - while if it was supported for consts too that makes it a new powerful
addition to the language allowing you to do something that was not possible
before.
So, the current state makes it less magic and more like monkeypatching.
But anyway, it's convenient.
feel like Rust traits and I like the trait pattern