Basic Swift data type, swift data type
Constants and variables
Constants and variables are represented by a specific name, such as maximumNumberOfLoginAttempt or welcomeMessage. A constant points to a specific type of value, such as a number of 10 or the character "hello ". The value of a variable can be modified as needed, but the value of a constant cannot be changed twice.
Declaration of constants and variables
Constants and variables must be declared before use. In Swift, use the let keyword to declare a constant, and the var keyword to declare a variable. Example:
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
The above code can be understood as:
Declare a constant called maximumNumberOfLoginAttempts with a value of 10. Then declare a variable currentLoginAttempt with an initial value of 0.
In this example, the maximum number of login attempts 10 is unchanged, so it is declared as a constant. The number of attempts to log in is variable, so it is defined as a variable. You can also declare multiple variables or constants in a line, separated by a, sign:
var x = 0.0, y = 0.0, z = 0.0
Note: If a value will not change in the following code, it should be declared as a constant using the let keyword. Variables are only used to store values that will change.
Type annotation
When declaring constants and variables, you can use annotations to indicate the type of the variable or constant. Use: sign, space, and type name to complete the type annotation after the variable or constant name. The following example declares a variable called welcomeMessage with the annotation type string String:
var welcomeMessage: String
The semicolon ":" is like saying:… is… type, so the above code can be understood as
Declare a variable called welcomeMessage, its type is String
This type annotation indicates that the welcomeMessage variable can store any string type value without error, such as welcomeMessage = "hello"
Note: Type annotations are rarely needed in actual programming. When defining constants or variables, Swift has determined the type information based on the initialized value. Swift can almost implicitly determine the type of a variable or constant.
semicolon
Unlike some other programming languages, Swift does not require a semicolon; to separate each statement. Of course, you can also choose to use a semicolon, or you want to write multiple statements in one line.
let cat = ""; println (cat)
// prints ""
Integer
Integers are numbers without fractions like 42 and -23, including signed (positive, negative, 0) and unsigned (positive, 0). Swift provides 8, 16, 32 and 64-bit numeric forms, similar to C language, you can use 8-bit unsigned integer UInt8, or 32-bit integer Int32. Like other Swift types, the first letter of these type names is capitalized
Integer boundary
Use min or max value to get the maximum and minimum value of the type, such as
let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8
These value boundary values distinguish the types of integers (such as UInt8), so they can be used in expressions like other values of this type without regard to benefits.
Int type
In general, programmers do not need to choose the number of integers when writing code. Swift provides an additional integer type Int, which is the same number of integers as the word length of the current machine environment.
On 32-bit machines, Int is the same size as Int32
On 64-bit machines, Int is the same size as Int64
Unless you really need to use a positive number with a specific word length, try to use the Int type. This ensures the portability of the code. Even on 32-bit platforms, Int can store values ranging from -2,147,483,648 to 2,147,483,647, which is sufficient for most positive numbers.
5. Floating point numbers
Floating point numbers are numbers with fractions like 3.14159, 0.1, -273.15. Floating-point numbers can express values that are wider (larger or smaller) than Int. Swift supports two types of signed floating point numbers:
The Double type can represent 64-bit signed floating point numbers. When the number of the table needs to be very large or the precision requirement is very high, you can use the Double type.
The Float type can represent 32-bit signed floating-point numbers. When the number to be expressed does not require 64-bit precision, you can use the Float type.
Note Double has at least 15 decimal places and Float has at least 6 decimal places. The appropriate number of decimal places depends on the range of floating point numbers in your code.
6. Type safety and type deduction
Swift is a type-safe language. Type safety means that you need to figure out the types of variables when programming. If your code part requires a string, you can't pass an integer type by mistake.
Because Swift is type-safe, it will check your code at compile time, and will report an error if any types do not match. This allows programmers to catch as soon as possible and fix errors as early as possible in the development process.
Type checking can help avoid errors when using different types of values. However, this does not mean that you must specify the type declared by each constant and variable. If you don't specify the type you need, Swift uses type deduction to specify the corresponding type. Type deduction enables the compiler to automatically derive the type of a specific expression through the initialization value you provide when compiling.
Type deduction makes Swift require fewer type declaration statements than C or Objective-C. Constants and variables are still explicitly typed, but most of the work of specifying their types has been done for you by Swift.
Type deduction is particularly useful when you declare a constant or variable and give the initial value type. This is usually done by assigning constant values to the declared constants or variables. (Constant values are the values that appear directly in the source code, as in Examples 42 and 3.14159 below.)
For example, if you specify 42 to a new constant variable without saying what type it is, Swift infers that the constant you want is an integer because you have initialized it to an integer
let meaningOfLife = 42
// meaningOfLife is inferred to be of typeInt
Similarly, if you do not specify the type of floating-point value, Swift infers that you want to create a Double:
let pi = 3.14159
// pi is inferred to be of type Double
Swift always chooses Double (not Float) when it needs a floating point type. If you add integers and floating-point numbers in an expression, a Double type is derived:
let anotherPi = 3 + 0.14159
// anotherPi is also inferred to be of typeDouble
Constant 3 does not show the specified type, so Swift derives the output type Double based on the floating-point value in the expression.
Numerical expression
Integer constants can be written as:
A decimal number without a prefix
A binary number, prefixed with 0b
An octal number, prefixed with 0o
A hexadecimal number, prefixed with 0x
All of these integer constants can be used to express the decimal value of 17 as follows
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary notation
let octalInteger = 0o21 // 17 in octal notation
let hexadecimalInteger = 0x11 // 17 inhexadecimal notation
Floating point can be decimal (without prefix) or hexadecimal (prefixed with 0x), and there must always be a decimal number (or hexadecimal number) on both sides of the decimal point. They can also have an optional exponent, represented by a uppercase or lowercase e for decimal floating point numbers, or uppercase / lowercase p for hexadecimal floating point numbers
The decimal number with exp exp, the actual value is equal to the base times the exp power of 10, such as:
1.25e2 means 1.25 × 102, or 125.0.
1.25e-2 means 1.25 × 10-2, or 0.0125.
The hexadecimal number with exp exp, the actual value is equal to the base number multiplied by the exp power of 2, such as:
0xFp2 means 15 × 22, or 60.0.
0xFp-2 means 15 × 2-2, or 3.75.
All of the following floating-point constants represent 12.1875 in decimal:
let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
Numeric values can contain additional formats to make them easier to read. Both integers and floating-point numbers can be padded with additional zeros and can contain underscores to increase readability. None of the above formats affect the value of the variable:
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
Numeric type conversion
Use the Int type for all common numeric integer constants and variables in the code, even if they are known to be non-negative. This means that the numeric constants and variables in the code are compatible with each other and can match the automatically derived types.
These numeric types should only be used if for some reason (performance, memory footprint, or other necessary optimizations) you really need to use other numeric types. In these cases, the use of explicitly specified length types helps to find out that the value range overflows, and should leave a document.
Integer conversion
The range of constants or variables that can be stored in an integer is different according to each numeric type. An Int8 constant or variable can store a number between -128 and 127, and a UInt8 constant or variable can store a number between 0 and 255. Incorrect assignment will cause the compiler to report an error:
let cannotBeNegative: UInt8 = -1
// UInt8 cannot store negative numbers, and so this will report an error
let tooBig: Int8 = Int8.max + 1
// Int8 cannot store a number larger thanits maximum value,
// and so this will also report an error
Because each numeric type can store a different range of values, you must gradually convert from the underlying numeric type. This prevents hidden conversion errors and helps clarify the intention of type conversion in your code.
To convert a specific number type to another, you need to define a new variable of the desired type and initialize it with the current value. In the following example, the constant twoThousand is of type UInt16, and the constant one is of type UINT8. They cannot be added directly because of different types. In contrast, this example calls UInt16 (one) to create a new variable of type UInt16 initialized with the value of the variable one, and uses this value to replace the original value in the operation:
let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16 (one)
Because both types of addition are UInt16, it is now possible to add. The output constant (twoThousandAndOne) is inferred to be of type UInt16 because it is the sum of the values of two UInt16.
SomeType (ofInitialValue) is Swift's default type conversion method. In terms of implementation, UInt16 has a constructor that accepts UINT8 values. This constructor is used to construct a new UInt16 variable from the existing UInt8. You cannot pass in any type of parameter, it must be a type that UInt16 initializes to accept the type. For how to extend existing types and specify acceptance of new types (including your own type definitions), see Extensions.
Integer and floating point conversion
The conversion between integer and floating point types must be explicitly declared
let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double (three) + pointOneFourOneFiveNine
// pi equals 3.14159, and is inferred to beof typde Double
Here, the value of the constant three is used to create a new variable of type Double, so that both sides of the expression are of the same type. Without this conversion, the addition operation will not be allowed. Vice versa, an integer type can be initialized with a double or float value:
let integerPi = Int (pi)
// integerPi equals 3, and is inferred tobe of type Int
When a new integer value is initialized in this way, the floating-point value is always truncated. This means that 4.75 becomes 4, and -3.9 becomes -3.
Note: The conversion rules for numeric type constants / variables are different from the conversion rules for numeric type constants. Constant value 3 can be directly connected with constant value 0.14159 adds up because constants don't have an explicit type. Their types are derived by the compiler.
Type alias
Type aliases are alternative names defined by existing types. You can use the typealias keyword to define type aliases. Type aliases can help you refer to an existing type with a more contextual name, such as when dealing with a foreign type with a specified length:
typealias AudioSample = UInt16
Once you have defined a type alias, you can use the alias wherever the original name may be used:
var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound is now 0
Here, AudioSample is defined as an alias for UInt16. Because it is an alias, calling AudioSample.min actually calls UInt16.min, which assigns an initial value of 0 to the maxAmplitudeFound variable.
Boolean type
The Boolean type in Swift is defined using Bool, also known as the Logical type, and the optional values are true and false:
let orangesAreOrange = true
let turnipsAreDelicious = false
Here the types of orangesAreOrange and turnipsAreDelicious are deduced as Bool because they are initialized by the constant value of Bool type. Like the Int and Double types, you do not need to explicitly give the data type when defining the Boolean type, you only need to directly assign the value to true or false. When a constant / variable is initialized with a constant value of a certain type, type deduction makes the Swift code more precise and readable. Boolean types are particularly applicable in conditional statements, such as in if statements
if turnipsAreDelicious {
println ("Mmm, tasty turnips!")
} else {
println ("Eww, turnips are horrible.")
}
// prints "Eww, turnips are horrible."
Conditional statements like if statements will be introduced in detail in the following chapter ControlFlow. Swift's type safety strategy will prevent other non-Boolean types from being converted to Boolean types, such as
let i = 1
if i {
// this example will not compile, and will report an error
}
An error will be reported, but this is feasible in other programming languages. But the following definition is correct:
let i = 1
if i == 1 {
// this example will compile successfully
}
The result of i == 1 is a boolean type, so it can pass the type check. Comparisons such as i == 1 will be discussed in the chapter [Basic Operators]. The example above is also an example of Swift type safety. Type safety avoids accidental type errors and ensures that the intent of the code is clear.
Tuple type
Tuple types can assemble a number of different data types into one element. These data types can be of any type and need not be of the same type.
In the following example, (404, "Not Found") is an HTTP status code. The HTTP status code is a specific status code returned when requesting a web page. The specific meaning of the 404 error is that the page was not found.
let http404Error = (404, “Not Found”)
// http404Error is of type (Int, String), and equals (404, "NotFound")
This tuple consists of an Int and a string. This combination contains both numbers and a string description that is easy for people to recognize. This tuple can be described as a tuple of type (Int, String).
Programmers can freely create their own tuple types, such as (Int, Int, Int), or (String, Bool) At the same time, the number of types of tuples is unlimited. The values of a tuple can be accessed separately as follows:
let (statusCode, statusMessage) = http404Error
print ("The status code is \ (statusCode)")
// prints "The status code is 404"
print ("The status message is \ (statusMessage)")
// prints "The status message is Not Found"
In addition, you can also use the element sequence number to select the value in the tuple, note that the sequence number starts from 0
print ("The status code is \ (http404Error.0)")
// prints "The status code is 404"
print ("The status message is \ (http404Error.1)")
// prints "The status message is Not Found"
When creating a tuple, you can also directly specify the name of each element, and then directly use the tuple name. Element name access, such as:
let http200Status = (statusCode: 200, description: "OK")
print ("The status code is \ (http200Status.statusCode)")
// prints "The status code is 200"
print ("The status message is \ (http200Status.description)")
// prints "The status message is OK"
The tuple type is particularly suitable when used as the return value of a function, and can return more information that the user needs for the function. For example, a function requesting a web page can return a tuple of (Int, String) type to represent the success or failure of the page acquisition. Returning tuples of two different types can provide more return information than returning only one value of one type. See Functions with Multiple Return Values for details
Optional type
When a value may not exist, an optional type can be used. This type of definition is: either this value exists and is equal to x, or it does not exist at this value.
Note: This type does not exist in C and Objective-C, but there is a similar type in Objective-C, called nil, but it is only useful for objects. In other cases, the Object-C method returns a special value (such as NSNotFound) to indicate that this value does not exist. This approach assumes that the method caller knows the existence and meaning of this special value. Swift's optional types help you define situations where any value does not exist.
An example is given below. In Swift, the String type has a method called toInt, which can convert a string to an Int type. However, it should be noted that not all strings can be converted to integers. For example, the string "123" can be converted to 123, but "hello, world" cannot be converted.
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt ()
// convertedNumber is inferred to be of type "Int?", or "optional Int"
Since the toInt method may fail, it will return an optional Int type, which is different from the Int type. An optional Int type is recorded as Int ?, not Int. The question mark indicates that its value is optional, an Int may be returned, or the returned value does not exist.
if statement and forced unpacking
Programmers can use if statements to detect whether an optional type contains a specific value. If an optional type does contain a value, it will return true in the if statement, otherwise it will return false. If you have checked and confirmed that the value exists, you can use it or output it. You only need to add an exclamation point (!) After the name when outputting, which means to tell the compiler: I have detected this value and can use It's gone. Such as:
if convertedNumber {
print ("\ (possibleNumber) has an integer value of \ (convertedNumber!)")
} else {
print ("\ (possibleNumber) could not be converted to an integer")
}
// prints "123 has an integer value of 123"
Conditional statements like if statements will be introduced in detail in the following chapter ControlFlow.
Select binding
Choosing a binding helps determine whether an optional value contains a value, and if so, converts the value into a temporary constant or variable. Selection binding can be used in if or while statements to check whether there is a value outside the optional type and extract possible values. See ControlFlow for details of if and while statements.
Methods as below:
if let constantName = someOptional {
statements
}
Then the previous example can also be rewritten as:
var myString: String?
myString = "Hello, Swift!"
if let yourString = myString {
print ("Your string has-\ (yourString)")
} else {
print ("Your string does not have a value")
}
Optional types for implicit unpacking
In the above example, the optional type indicates that a constant / variable may have no value. Optional types can be checked by the if statement for value, and can be unwrapped by optional binding.
But in some cases, optional types are always valid, so you can implicitly remove the type check by definition and force the use of optional types. These optional types are called implicit unpacking optional types. You can add directly after the type! Instead? To specify.
The optional type of implicit unpacking is mainly used when the value of a variable / constant will definitely exist after the definition is completed in an instant. This is mainly used in the initialization process of the class, see Unowned References and Implicitly Unwrapped Optional Properties.
The optional type of implicit unpacking is essentially an optional type, but it can be used as a general type without verifying whether the value exists every time. The following example shows the difference between optional types and unwrapped optional types.
let possibleString: String? = "An optional string."
print (possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."
let assumedString: String! = "An implicitly unwrapped optional string."
print (assumedString) // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."
You can think of implicit unwrapping optional types as optional types that are automatically unwrapped each time they are used. That is not to add after variable / constant every time it is used! It is added directly at the time of definition.
Note: If an implicitly unpacked optional type does not contain an actual value, then access to it will throw a runtime error. Add after the variable / constant name! The situation is the same.
You can still use the unpacked optional type as a normal optional type to detect whether there is a value.
if assumedString {
print (assumedString)
}
// prints "An implicitly unwrapped optional string."
Or check by selecting the binding
if let definiteString = assumedString {
print (definiteString)
}
// prints "An implicitly unwrapp
ed optional string. "
Note: If there is a possibility that an optional type has no value, the unpacked optional type should not be used. In this case, be sure to use the normal optional type.
assertion
Optional types allow programmers to detect the existence of a value at runtime, and then use code to handle the absence. But in some cases, if a value does not exist or the value does not meet the conditions will directly affect the execution of the code, this time you need to use an assertion. In this case, the assertion ends the execution of the program to provide a basis for debugging.
Use assert debugging
Assertions are a method of detecting whether a condition is true in real time, that is, the assertion assumes that the condition is true. Assertions ensure that the execution of subsequent code depends on the establishment of conditions. If the condition is met, then the code continues to execute, if this condition is false, then the code will interrupt execution.
In Xcode, if you break during debugging, you can view the program status when the assertion fails by viewing the debug statement. Assertions can also provide suitable debug information. Use the global function assert to debug with asserts. The assert function accepts a boolean expression and a message displayed when the assertion fails, such as:
let age = -3
assert (age> = 0, "A person's age cannot be less than zero")
// this causes the assertion to trigger, because age is not> = 0
When the current condition returns false, the following error log will be output.
In this example, only when age> = 0, the condition is determined to be true, but age = -3, so the condition is determined to be false, and the error log "A person ’s age cannot be less than zero" is output.
Of course, the error log can also be omitted, but this is not conducive to debugging, such as
assert (age> = 0)
When to use assertions
It is used when it is necessary to detect a condition that may be false, but the code must return true. Here are some common scenarios that may use assertion detection:
When passing an integer type index, such as the Index of an array, this value may be too small or too large, causing the array to cross the boundary;
The parameter passed to the function, but an invalid parameter will not be executed in the function
An optional type is now nil, but in the following code, it needs a non-nil value to continue running.
See Subscripts and Functions for details
Note: Assertion will cause the program to stop, so if the exception is expected to occur, then the assertion is inappropriate. In this case, an exception is more appropriate. Assertions ensure that errors will be discovered during the development process, and it is best not to use them in published applications.