Working with Variables and Constants
1. Declaring Variables
| Declaration | Type Inference | Explicit Typing | Notes |
|---|---|---|---|
| var variableName | var variableName = 42 |
var variableName: Int = 42 |
Mutable variable; value can be changed after declaration |
| let constantName | let constantName = "Hello" |
let constantName: String = "Hello" |
Immutable constant; value must be set at declaration |
Example: Variable Declaration
var age = 25
age = 26 // Valid: variable can be reassigned
let name = "Alice"
// name = "Bob" // Invalid: constant cannot be reassigned
2. Declaring Constants
| Declaration | Type Inference | Explicit Typing | Notes |
|---|---|---|---|
| let constantName = "value" | String |
let constantName: String = "value" |
Constant cannot be reassigned; type inferred from initializer |
| let number = 42 | Int |
let number: Int = 42 |
Constant with explicit type annotation |
| let pi = 3.14159 | Double |
let pi: Double = 3.14159 |
Double precision floating-point constant |
Example: Declaring and Using Constants
let appName = "MyApp"
let version = "1.0.0"
let maxUsers = 1000
print("App: \(appName), Version: \(version)")
// Output: App: MyApp, Version: 1.0.0
Note: Constants are immutable and must be initialized at declaration time.
3. Understanding Type Inference
| Declaration | Type | Inferred Type | Notes |
|---|---|---|---|
| let constant = "Hello" | String |
String |
String literal inferred as String |
| var variable = 42 | Int |
Int |
Numeric literal inferred as Int |
| let pi = 3.14159 | Double |
Double |
Floating-point literal inferred as Double |
| let isTrue = true | Bool |
Bool |
Boolean literal inferred as Bool |
| let array = [1, 2, 3] | [Int] |
[Int] |
Array literal with Int elements inferred as [Int] |
| let dict = ["key": "value"] | [String: String] |
[String: String] |
Dictionary literal inferred as [String: String] |
Example: Type Inference in Action
let greeting = "Hello, World!"
let count = 5
let piValue = 3.14159
print(greeting) // "Hello, World!"
print(count) // 5
print(piValue) // 3.14159
Note: Swift infers the most specific type possible from the initializer value. For example,
3.14 is inferred as Double, not Float.
Warning: Type inference does not work for variables initialized to
nil or Optional values without explicit type annotation.
Example: Ambiguous Type Inference
let ambiguous = 42
// Swift infers this as Int
let another = "Swift"
// Swift infers this as String
4. Using Explicit Type Annotations
| Declaration | Type | Description |
|---|---|---|
| var variableName: Int | Int |
Explicitly declares a variable as an integer type |
| let constantName: String | String |
Explicitly declares a constant as a string type |
| var arrayVar: [String] | [String] |
Declares a mutable array of strings |
| let dictConst: [String: Int] | [String: Int] |
Declares an immutable dictionary with string keys and integer values |
Example: Declaring Variables with Explicit Types
var age: Int = 25
let name: String = "Alice"
var scores: [Int] = [85, 90, 78]
let grades: [String: Int] = ["Math": 95, "Science": 88]
Note: Type annotations are optional when Swift can infer the type from the initializer.
5. Working with Optionals (?, !)
| Property | Description | Usage |
|---|---|---|
| Optional Type | Represents a value that may or may not exist | var name: String? |
| Implicitly Unwrapped Optional | Assumes a value exists at runtime, but can still be nil | var name: String! |
| Force Unwrapping | Accesses the value of an optional, crashes if nil | name! |
| Optional Chaining | Safely accesses properties or methods of an optional | object?.property? |
Example: Optional Binding
let optionalValue: String? = "Hello"
if let value = optionalValue {
print(value) // Prints: Hello
}
Example: Nil Coalescing Operator
let optionalValue: String? = nil
let value = optionalValue ?? "Default"
print(value) // Prints: Default
Note: Use optional binding (
if let) to safely unwrap optionals and avoid runtime crashes.Warning: Force unwrapping (
!) can cause runtime crashes if the optional is nil.6. Understanding Implicitly Unwrapped Optionals (!)
| Property | Description | Usage |
|---|---|---|
| Implicitly Unwrapped Optional | An optional that is assumed to have a value at the time of use | Declared with ! after type, e.g., var name: String! |
| Initialization | Can be declared without an initial value | var optionalValue: String! |
| Access Behavior | Accessed directly without unwrapping, but will crash if nil | print(optionalValue) — crashes if nil |
Example: Declaring and Using Implicitly Unwrapped Optionals
var implicitOptional: String! = "Hello"
print(implicitOptional) // Prints "Hello"
implicitOptional = nil
// print(implicitOptional) // Crashes at runtime if accessed here
Note: Implicitly unwrapped optionals are useful when a variable will definitely have a value by the time it's accessed, but Swift cannot guarantee that at compile time. They should be used carefully to avoid runtime crashes.
7. Using Optional Binding (if let, guard let)
| Binding Type | Syntax | Description | Use Case |
|---|---|---|---|
| if let | if let unwrapped = optionalValue { ... } |
Binds an optional to a constant if it contains a value | Safe unwrapping when you want to proceed only if the value exists |
| guard let | guard let unwrapped = optionalValue else { return } |
Binds an optional to a constant and exits the current scope if it's nil | Early exit in functions or methods to avoid deeply nested code |
Example: Using if let
let optionalString: String? = "Hello, Swift!"
if let greeting = optionalString {
print(greeting) // Prints: Hello, Swift!
}
Example: Using guard let
func processName(_ name: String?) {
guard let unwrappedName = name else {
print("Name is missing")
return
}
print("Processing: \(unwrappedName)")
}
processName(nil) // Prints: Name is missing
processName("Alice") // Prints: Processing: Alice
Note:
if let is used for safe unwrapping inside a conditional block, while guard let is used to exit early from a function or scope if the optional is nil.
8. Using Optional Chaining (?.)
Optional chaining allows you to safely access properties, methods, and subscripts of optional values without explicitly unwrapping them.
| Feature | Description | Example |
|---|---|---|
| Optional Chaining Operator | Used to access properties or methods of an optional value that might be nil. | object?.property |
| Method Chaining | Allows calling methods on optional values safely. | object?.method() |
| Subscript Access | Access elements in an optional array or dictionary using optional chaining. | array?[index] |
Example: Safe Property Access
class Person {
var name: String?
var address: Address?
}
class Address {
var street: String?
}
let person = Person()
person.address = Address()
// Safe access using optional chaining
let street = person.address?.street // Returns Optional(String) or nil
Example: Method Chaining
class Calculator {
func calculate() -> Int? {
return 42
}
}
let calc = Calculator()
let result = calc.calculate?() // Returns Optional(Int) or nil
Note: If the optional value is nil, the entire expression evaluates to nil and no further operations are performed.
9. Using Nil Coalescing Operator (??)
| Operator | Description | Example |
|---|---|---|
| ?? | Returns the left operand if it's not nil; otherwise, returns the right operand. | |
Example: Safe Unwrapping with Nil Coalescing
let userAge: Int? = nil
let defaultAge = userAge ?? 18
print(defaultAge) // Prints: 18
Note: The nil coalescing operator is a shorthand for optional unwrapping and provides a default value when the optional is
nil.10. Working with Tuples
| Property | Description | Example |
|---|---|---|
| Declaration | Tuples are declared using parentheses with comma-separated values. | (name: "John", age: 30) |
| Access by Index | Access elements using 0-based index. | tuple.0 |
| Access by Name | Access elements using named properties. | tuple.name |