adwaita.docc/Tutorial/Swift/LearnSwift.tutorial
2024-04-13 21:41:48 +02:00

263 lines
13 KiB
Plaintext

@Article {
@Intro(title: "Learn Swift") {
Get to know concepts of the Swift programming language useful for _Adwaita for Swift_ and find additional resources.
}
@ContentAndMedia {
# Learn Swift
This is a quick overview over the Swift features relevant for _Adwaita for Swift_.
It's not intended to teach Swift to beginners, instead, it can be used for finding online material, to check whether you know the required concepts, and as a reference for later in the tutorial.
The official Swift tour is available [here](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/guidedtour) and there's a more detailed tutorial starting with [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics).
You'll find links to relevant chapters in the "Additional information" boxes after every section on this page.
Other great resources are [100 Days of Swift](https://www.hackingwithswift.com/100), [Swift for C++ Practitioners](https://www.douggregor.net/posts/swift-for-cxx-practitioners-value-types/), [Swift Playgrounds](https://developer.apple.com/swift-playgrounds/) (Apple platforms only), and [WWDC videos](https://developer.apple.com/videos/swift/).
If you prefer, continue the tutorial without worrying about those Swift concepts, and learn Swift while learning how to create apps.
}
@ContentAndMedia {
# Swift concepts
This is a simple hello world program written in Swift:
```swift
print("Hello, world!")
```
## Functions
`print` is a function accepting an argument. Create your own functions using the `func` keyword:
```swift
func say(_ message: String, to person: String) {
print("\(message), \(person)!")
}
// Call the function
say("Hello", to: "Peter") // Hello, Peter!
```
> Additional information:
> Dont understand the code, or interested in learning more about a topic?
> The additional information block is available at the end of every section.
> - [Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions)
> - [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics)
> - [Strings and Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters)
## Structures
As one can see in the example, Swift provides the basic data type `String` for text.
There are different groups of types in Swift.
The most often used ones, especially with _Adwaita for Swift_, are structures:
```swift
struct Rectangle {
var width: Int
var height: Int
var area: Int {
width * height
}
}
// Create an instance
let rectangle = Rectangle(width: 30, height: 20)
print(rectangle.area) // 600
```
In this code snippet, there is a number of new patterns:
- `let rectangle = Rectangle(width: 30, height: 20)` assigns a value of the type `Rectangle` to a constant. The constant can be called by its name `rectangle` after the declaration.
- `width` is a stored property of the type `Int`, the basic data type for integers, on the structure `Rectangle`. As the name suggests, it stores a value on an instance of the type.
- `area` on the other hand is a computed property. It is a property that is calculated when it gets called instead of storing a value.
- Call a property using the syntax `instance.property`.
> Additional information:
> - [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics)
> - [Basic Operators](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators)
> - [Structures and Classes](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures)
> - [Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions)
> - [Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties)
> - [Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization)
## Methods
Methods are functions that are defined on top of types, most importantly structures.
```swift
struct Cat {
var name: String
func hasName(_ name: String) -> Bool {
self.name == name
}
mutating func rename(to newName: String) {
name = newName
}
}
// Create an instance
print(Cat(name: "Fred").hasName("Bob")) // false
// Save an instance to a variable
var cat = Cat(name: "Steve")
cat.rename(to: "Peter")
print(cat.name) // Peter
```
In this code snippet, there are the following new patterns:
- `var cat = Cat(name: "Steve")` assigns a value of the type `Cat` to a variable. The constant can be called _and modified_ by its name `cat` after the declaration.
- A method definition starting with `mutating` can modify the properties while it runs. Nonmutating functions normally return a value, similar to computed properties, they cannot change the instance.
- Call a method using the syntax `instance.method()`, and specify parameters if necessary.
- As you saw before, you can access properties (and also methods) from within a type directly by its name. `self` refers to the instance it runs on, so `self.name` also calls the property `name`.
> Additional information:
> - [Methods](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/methods)
> - [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics)
> - [Strings and Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters)
> - [Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions)
> - [Structures and Classes](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures)
> - [Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties)
> - [Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization)
## Modifiers
Modifiers are special methods that, instead of mutating an instance, create a copy of an instance, modify the copy and return the copy.
```swift
struct Box {
var isOpen = false
func open(_ isOpen: Bool = true) -> Self {
var newSelf = self
newSelf.isOpen = isOpen
return newSelf
}
}
// Save an instance to a variable
var box = Box().open().open(false).open()
print(box.isOpen) // false
```
The new concepts are:
- `Self` (with a capital "S") refers to the type it is defined on (in this case `Box`).
- In all the previous example, the `return` keyword has been omitted for returning values because Swift allows this for bodies with a single line only. As this function's body spans multiple lines, the `return` keyword is required.
> Additional information:
> - [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics)
> - [Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions)
> - [Structures and Classes](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures)
> - [Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties)
> - [Methods](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/methods)
> - [Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization)
## Closures
You cannot only pass values as parameters, but also functions. This can be done using a special syntax called closure expression syntax.
```swift
func run(function: () -> Void) {
function()
}
// Call the run function
run {
print("Hello, world!")
} // Hello, world!
```
`() -> Void` is the type of a function that accepts no argument (`()`) and returns nothing (`Void`).
It's also possible to use parameters within closures, and return a value:
```swift
func modifyAndPrint(string: String, modify: (String) -> String) {
print(modify(string))
}
// Call the modifyAndPrint function
modifyAndPrint(string: "Hello") { string in
"\(string), world!"
} // Hello, world!
```
> Additional information:
> - [Closures](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures)
> - [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics)
> - [Strings and Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters)
> - [Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions)
## Protocols
A protocol is a type that defines requirements for structures and other types.
It cannot be initialized itself, but implemented by other types.
```swift
protocol Named {
var name: String { get }
}
// Adopt the protocol by a structure
struct Cat: Named {
// This property is required to conform to the protocol (it can be stored or computed)
var name: String
}
let namedSpecies: Named = Cat(name: "Bob")
print(namedSpecies.name) // Bob
```
`var name: String { get }` defines that the property `name` must be available. If it were `var name: String { get set }`, a constant or simple computed variable wouldn't work since the property has to be mutable.
You can see that a type cannot only be specified explicitly for properties, but for any variable or constant. Without the `: Named`, the type of `namedSpecies` would be `Cat`.
Setting the type to `Named` allows it to take a value of any type conforming to the `Named` protocol.
> Additional information:
> - [Protocols](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols)
> - [The Basics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics)
> - [Strings and Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters)
> - [Structures and Classes](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures)
> - [Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties)
> - [Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization)
> - [Opaque and Boxed Types](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes)
## Property wrappers
A property wrapper is a structure that is designed to wrap a property, meaning that it controls how a property is stored.
```swift
@propertyWrapper
struct Percentage {
private var number = 0
var wrappedValue: Int {
get {
number
}
set {
if newValue >= 0 && newValue <= 100 {
number = newValue
}
}
}
}
struct Transportation {
// Use the property wrapper
@Percentage var train: Int
}
var transportation = Transportation()
transportation.train = 63
print(transportation.train) // 63
transportation.train = 104
print(transportation.train) // 63
```
In this code example, you can see different new concepts:
- `private` determines that `number` is not visible outside the structure.
- The computed property `wrappedValue` contains a getter and a setter. So far, we have seen computed variables with a getter only. The setter handles assignments with `=`, as you have seen for stored properties already.
- Use a property wrapper by adding the @ symbol to the beginning of the struct's name.
}
}