In this post, I’ll show the fundamentals of the Swift language. It’s the first of a series where I’ll show how to build a chat app using Swift and SwiftUI.
Let’s start with the simpler things, comments, variables and constants:
// It's a line comment /* This is a multiline comment */ // Variable definition: // var varname: Type = Initial value var name: String = "Nicola"
The variables are defined using the “var” keyword, a name, after the “:” we must write the type of the variable (String, Double, Float, Array, Set,..)
The variable can be also declared shortly, omitting the type and setting directly the value, in this case, the variable gets the type of the value.
// declaring an int variable omitting the type var age: 10 // age is an integer
The constants are declared in the same way, apart from using the “let” keyword and that they can get only a value that can be changed.
let pi = 3.14 pi = 4 // Error can't change costant value
In Swift we can declare a variable as optional, the variable can assume every value of the type defined and the “null” value. In this way, the nulla value became a possible value for that variable. An optional variable is defined appending the “?” to the type:
var myOpt: Int? myOpt = 3 // to get the myOpt value if let value = myOpt { print("Value \(value)") } else { print("null") } // it's equivalent to if myOpt != nul { var value = myOpt! print("Value \(value)") } else { print("null") }
Note the “!” after myOpt, using the “!” we force to get the value of myOpt. Use it only when you are sure that the variable is not null, otherwise you can have some crash due to null pointer exception.
About the conditional statement, you find the classic:
if condtion { } else if condition { } else { } // Locic operator // && for a and b // || for a or b // == for a equal b // != for b not equal b
In swift the “condition” not need to have enclosed in () how in other languages (i.e. C).
See other types: Array, Tuple and Set.
// Array declaration // var name: Array<Type> // Example var numbers: Array<Int> // at this moment the numbers is nill // To be able to make operation on the array we must initialize numbers = Array<Int>() // now we have an empty array numbers.append(3) // add the number 3 numbers.append(1) // add the number 1
To iterate the elements of the array (or other collections) we need the control flow, in this case, the for loop.
for i in 0..<numbers.count { // from zero to 1 print("numbers[\(i)] = \(numbers[i])") }
In the previous code we iterate the numbers vector operating on a sequence in the range 0..<numbers.count . In this case 0..<2, mean that i can assume the value 0,1.
A range can be defined in this way:
var firstTenA = 0...10 // all the number from 0 to 10 var firstTenB = 0..<11 // all the number from 0 to 10 // with the < we exclude the value on the right // Other version of the for loop see before for i in 0...(numbers.count - 1) { // from zero to 1 print("numbers[\(i)] = \(numbers[i])") }
Note if you want to iterate in reverse order, you must use the reverse method :
for i in (0..<numbers.count).reversed() { print("numbers[\(i)] = \(numbers[i])") }
It possible also iterate directly on the vector:
for elem in numbers { print(elem) }
About the iteration, look at the String, we can’t iterate the string with int index but using the indices.
var name: String = "Bob" // write every single character of the string for i in name.indices { print(name[i]) }
Other controls flow: while and repeat while
var counter = 10 while counter > 0 { print(counter) counter = counter - 1 } repeat { print(counter) counter = counter + 1 } while counter < 10
How in other programming languages the code in the while is executed until the condition is true, instead of with the repeat while, the code is executed at least one time.
Another collection type is the dictionary, it’s a list of pair key and value.
var dict: [Int: String] = [Int: String]() dict[404] = "Not found" for key in dict.keys { print(key) } for value in dict.values { print(value) }
In the code, we see the declaration of a dictionary where the key is an Int and the value is a String. It’s possible to access the element using the key in [], instead, it’s possible to iterate the key and the values using the methods keys and values.
The next step is to see how to declare and use the functions.
func nameLastName(name a: String, lastname b: String ) { print("Name \(a) Lastname \(b)") }
The function is declared using the keyword func, the parameters are passed indicating a label, a name of the parameter and the type.
You can see the label as a help for the programmer, it explains what the parameter means, instead the name is used in the body of the function. To invoke that function:
nameLastName(name: "Bob", lastname: "Rossi")
It’s possible to declare also the function without the labels:
func nameLastName(a: String, b: String ) { print("Name \(a) Lastname \(b)") } // In this case the function is called in this way nameLastName(a: "Bob", b: "Rossi")
In the end, it’s possible to declare the function to avoid the use of the name in the call.
func nameLastName(_ a: String, b: String ) { print("Name \(a) Lastname \(b)") } // In this case the function is called in this way nameLastName("Bob", b: "Rossi")
The function can return also a value:
// Function that returns an Int func squareRect(width: Int, height: Int) -> Int { let sup = width * height return sup } print(squareRect(width: 4, height: 5))
The type returned is indicated by the symbol “->”.
In Swift the parameter are passed for value, it means that we can’t change the value of the parameters in the body of the function, to make it we have to use the keyword inout in this way:
// Swap the value of two element func swap(a: inout Int, b: inout Int) { let dum = a a = b b = dum } var first = 3 var second = 4 // Call the functions using "&" near the parameters swap(a: &first, b: &second)
A type a bit different from other languages is the Enum. Here an example:
enum Polar: Int { case north = 1 case sud, west, est func description() -> String{ switch self { case .north: return "North" case .est: return "Est" case .west: return "West" case .sud: return "Sud" } } }
The enum can have also a type (Int in the example), it’s possible to assign a specified value at every element of the enum. The big difference in Swift is that it’s possible to declare also e function in an Enum and invoke it.
var sanFrancisco = Polar.west print(sanFrancisco.description()) // print "West"
Now see the data structure, the first one is the struct.
struct Coordinate { var lat: Double var long: Double func xy() { print("Lat = \(lat) and Long = \(long)") } }
How in the example the struct is a data structure that can contain properties (variables, constants) and methods (function).
Very similar is also the declaration of the class:
class ClassCoordinate { var lat: Double var lon: Double init(lat: Double, lon: Double) { self.lat = lat self.lon = lon } func invert() { let dum = lat lat = lon lon = dum } func coord() -> String { return ("(\(lat),\(lon))") } }
The big difference between class and the structures is that the struct is a value type, so if we have two variables of the same structure type, and assign the second to one, in the first is copied the value of the second.
var coordA = Coordinate(lat: 37.3382, long: 121.8863) var coordB = Coordinate(lat: 37.3382, long: 121.8864) var coordC = Coordinate(lat: 37.3382, long: 121.8865) print("Point A \(coordA) Point B \(coordB)") coordA = coordB print("Point A \(coordA) Point B \(coordB)") coordB = coordC print("Point A \(coordA) Point B \(coordB)") /* Produce this output Point A Coordinate(lat: 37.3382, long: 121.8863) Point B Coordinate(lat: 37.3382, long: 121.8864) Point A Coordinate(lat: 37.3382, long: 121.8864) Point B Coordinate(lat: 37.3382, long: 121.8864) Point A Coordinate(lat: 37.3382, long: 121.8864) Point B Coordinate(lat: 37.3382, long: 121.8865) */
With the class it’s is different, the class is a reference type, so when a second class is assigned to the first class, is not copied the value but the reference, so they are the same object. If you change one, change the values of the other.
var coordClassA = ClassCoordinate(lat: 37.3382, lon: 121.8863) var coordClassB = ClassCoordinate(lat: 37.3382, lon: 121.8864) print("Point A \(coordClassA.coord()) Point B \(coordClassB.coord())") coordClassA = coordClassB print("Point A \(coordClassA.coord()) Point B \(coordClassB.coord())") coordClassB.lat = 1 coordClassB.lon = 2 print("Point A \(coordClassA.coord()) Point B \(coordClassB.coord())") /* The output is Point A Coordinate(lat: 37.3382, long: 121.8863) Point B Coordinate(lat: 37.3382, long: 121.8864) Point A Coordinate(lat: 37.3382, long: 121.8864) Point B Coordinate(lat: 37.3382, long: 121.8864) Point A Coordinate(lat: 37.3382, long: 121.8864) Point B Coordinate(lat: 37.3382, long: 121.8865) Point A (37.3382,121.8863) Point B (37.3382,121.8864) Point A (37.3382,121.8864) Point B (37.3382,121.8864) Point A (1.0,2.0) Point B (1.0,2.0) */
When to use the struct and when to use the class? When the data struct is big is better to use a class because the reference doesn’t duplicate data (and consuming memory) but the reference requires more attention.
To conclude I introduce the protocol, it’s defined in the Swift documentation as: “A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality”. If a class have to conform to a protocol it must implement the function and property request from the protocol.
protocol PrintProtocol { var simpleLabel: String {get} mutating func translate() } class CoordinateClass: PrintProtocol { var lat: Double var lon: Double var simpleLabel: String = "" init(a: Double, b: Double) { self.lat = a self.lon = b } func translate() { self.lat = self.lat * 2 self.lon = self.lon * 2 } }
In this case, the PrintProtocol requires that a class that using it, have to declare a variable simpleLabel (get, it possible read the value) and implement a function translate. This function is mutating, it can modify the property of the class.
In the next post, I’ll start to talk about SwiftUI. This post is not frozen, I’ll change it to improve or add important things that I skipped for now.
Note: English is not my native language, so I’m sorry for some errors. I appreciate it if your correct me.