Black Friday Black Friday
Black Friday ultimate sale! Get up to 80 % extra free points! More information here

Lesson 3 - More on the Swift type system: Data types

Swift Basic constructs More on the Swift type system: Data types

In the previous lesson, Variables, type system and parsing in Swift, we learned basic data types of Swift. These were Int, Double, and String. In today's Swift tutorial, we're going to look at them in more detail and explain how to use them correctly. Today is going to be more theoretical, and the next lesson will be very practical. At the end, we'll make a few simple examples.

Swift recognizes two kinds of datatypes, value and reference. We'll discuss the reference data types later.

Value data types

We can easily imagine a variable of the value data type. It can be, for example, a number or a character. The value is stored directly in memory and can be accessed directly from the program. Note how I've used the word "directly" so many times. In the lessons throughout this course, we'll mainly be working with these variables.

Whole-number data types

Let's look at the table of all of the built-in whole-number data types in Swift. Notice the Int type, which we already know.

Data type Range Size
Int -2 147 483 648 to 2 147 483 647 32 bits
UInt 0 to 4 294 967 295 32 bits

Of course, you don't have to memorize all these types, you can use just Int to store whole numbers.

You can find more information in the official documentation. See Help -> Developer Documentation and check it out. Then it's just about searching. You can easily get information about specific data types in the Quick Help inspector in Xcode on the right. Just select text with e.g. the Int type in your code and click Structure Reference in the inspector.

The U prefix in UInt means that it doesn't allow to store negative values and can therefore store a positive value twice as large. These types are called unsigned, the classic ones are called signed.

Decimal numbers

For decimal numbers, the situation is similar, we can only choose between two data types. They differ in the range of values, and also in precision, i.e. in the number of decimal places. The Double datatype is twice as precise as Float, which you probably deduced from its name.

Data type Range Precision
Float +-1.5 * 10−45 to +-3.4 * 1038 7 numbers
Double +-5.0 * 10−324 to +-1.7 * 10308 15-16 number

Due to the fact that decimal numbers are stored in your computer in a binary system, there is some precision loss. Although the deviation is almost negligible, if you're programming, e.g. a financial system, don't use these data types for storing money since it could lead to slight deviations.

When we want to assign a value to a Float variable in source code, we have to specify the type explicitly. We don't have to do this with Double since it's the default decimal type:

let f : Float = 3.14
let d = 2.72

As the decimal separator in source code, we use dots, regardless of our macOS regional settings.

Other built-in data types

Let's look at the other data types that Swift offers:

Data type Range Size/Precision
Character U+0000 to U+ffff 16 bits
Decimal +-1.0 * 10−28 to +-7.9 * 1028 28-29 numbers
Bool True or False 8 bits

Character

Character represents one character, unlike String, which represents the entire string of Characters. We declare characters with quotation marks in Swift and it's necessary to declare the data type, otherwise it'd be String:

let c : Character = "A"

Decimal

The Decimal type solves the problem of storing decimal numbers in binary form, because it stores the number internally similarly as text. It's therefore used for storing monetary values. For all other mathematical operations with decimal numbers we use Double or` Float. We have to specify the data type as well to declare `Decimal values:

let number : Decimal = 3.14159265358979323846

Bool

Variables of the Bool type can contain only two values: true or false. We'll use them when we get to conditions. In a variable of the Bool type, we can store either true/false or a logical expression. Let's try a simple example:

let b = false
let expression = 15 > 5
print(b)
print(expression)

The program output:

false
true

We may enclose expressions in parentheses. That may be useful when we have more of them. Notice that the expression is equal to true since 15 is in fact more than 5. Going from expressions to conditions isn't a far stretch, but we'll go into them in the next lesson.

String

The data type that you will see on every corner. Represents a string of characters, just any text. It's a value type. We'll introduce the most important methods that are good to know or at least it's good to know they exist. Test these methods in the Command Line, not in Playground.

contains(), hasSuffix() a hasPreffix()

We can ask if a String starts with, ends with or contains a substring. A substring is a part of a String. All of these methods will take a substring as a parameter and return Bool (true/false). We can't react to the output yet; however, let's write the return values nonetheless:

let s = "Rhinopotamus"
print(s.hasPreffix("rhin"))
print(s.hasSuffix("tamus"))
print(s.contains("pot"))
print(s.contains("lol"))

The program output:

false
true
true
false

We can see that everything works as expected. The first phrase failed, as expected, because the string actually starts with a capital letter.

uppercased() and lowercased()

Distinguishing between capital and lowercase letters is not always what we want. We'll often need to ask about the presence of a substring in a case-insensitive way. The situation can be solved using the uppercased() and lowercased() methods which return the string in uppercase, resp. lowercase. Let's make a more realistic example than Rhinopotamus. The variable will contain a line from some configuration file, which was written by the user. Since we can't rely on the user's input we'll try to eliminate possible errors, here by ignoring letter cases.

var config = "Fullscreen shaDows autosave"
config = config.lowercased()
print("Will the game run in fullscreen?")
print(config.contains("fullscreen"))
print("Will shadows be turned on?")
print(config.contains("shadows"))
print("Will sound be turned off?")
print(config.contains("nosound"))
print("Would the player like to use autosave?")
print(config.contains("autosave"))

The program output:

Will the game run in fullscreen?
true
Will shadows be turned on?
true
Will sound be turned off?
false
Would the player like to use autosave?
true

We can see that we're able to detect the presence of particular words in a string. First, we convert the entire string to lowercase or uppercase, and then check the presence of the word in lowercase or uppercase, respectively. By the way, simple processing of configuration script may actually look like this.

trimmingCharac­ters()

Another issue that may arise with user inputs is accented characters. Swift, fortunately, works fully in Unicode. Which means that diacritics can hardly corrupt our code. Always consider that most the people around the world don't speak English as their primary language, so your application should support their regional characters if you want them to use it...which you should. Another pitfall can be whitespace characters, which are not visible for users, but can cause program errors. Generally, it's a good idea to trim any input from the user. We are provided with the trimmingCharacters(in: ) method to which we specify what we want to trim. Because it's an enumeration, we can write a dot . and Xcode will suggest a large variety of options what to trim. You'll most likely use the .whitespacesAndNewlines option, removing all white characters and new-line characters around the string.

print("Enter a number:")
let s = readLine()!
print("Here's what you originally wrote: " + s)
print("Your text after the trim function: " + s.trimmingCharacters(in: .whitespacesAndNewLines))
let a = Int(s)!
print("I converted the text you entered to a number. Here it is: \(a)")

replacingOccu­rrences()

Probably the most important method on String is a replacement of its parts with another text. We enter two substrings as parameters, the first one is the one want to be replaced and the second one will replace it. The method returns a new String in which the replacing occurred. When the method doesn't find the substring, it returns the original string. Let's try:

let s = "Java is the best!"
let replaced = s.replacingOccurrences(of: "Java", with: "Swift")
print(replaced)

We'll get:

Swift is the best!

String interpolation

We've already mentioned the string interpolation. In Swift, if we want to insert variables on specific positions in a string, we wrap them in \() and write them directly into the string:

let a = 10
let b = 20
let c = a + b
let s = "When we add $a and $b, we get $c"

The program's output:

When we add 10 and 20, we get 30

This is a very useful and easy way to build strings. If we want to print numbers, we can't avoid it. For combining string variables with another strings, we can use string concatenation (simply use + to merge them into a single string).

The count property

The last but most important property (NOT a method) is count, i.e. the total number of characters. It returns an integer that represents the number of characters of the string. We don't use parentheses because properties don't have parameters. It'd make more sense if it was named length, but that's something we have to get used to.

print("Type in your name:")
let name = readLine()!
print("Your name is \(name.count) characters long.")

Padding

To pad a string means to add few characters to the String so it has the required length. It's often used to add spaces, but you can add any characters you wish. Some languages offer useful methods for padding from the left or right. Swift has only one and it requires a lot of parameters. We'll describe them in detail further in the course.

If some of the methods in this lesson don't work for you, make sure you added import Foundation to your file for importing the basic Swift functionality.

There's still a lot to go over and lots of other data types that we haven't covered. Regardless, there is a time for everything. In the next lesson, Conditions (branching) in Swift, we'll introduce conditions and then loops, then we'll have enough knowledge to create interesting programs :)


 

 

Article has been written for you by Filip Němeček
Avatar
Do you like this article?
No one has rated this quite yet, be the first one!
Thumbnail
All articles in this section
Swift basic constructs
Activities (4)

 

 

Comments

To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

No one has commented yet - be the first!