Swift Advanced Operators
Powerful operators for complex operations
⚡ What are Advanced Operators?
Advanced operators in Swift provide powerful ways to manipulate data including bitwise operations, overflow operators, and custom operators. They enable low-level programming and mathematical computations.
// Bitwise AND operator
let result = 0b1010 & 0b1100 // Binary: 1000 (8 in decimal)
print("Bitwise AND: \(result)")
// Nil-coalescing operator
let name: String? = nil
let displayName = name ?? "Guest"
print("Welcome, \(displayName)!")
Output:
Bitwise AND: 8
Welcome, Guest!
Advanced Operator Types
Bitwise Operators
Work with individual bits of data
let a = 0b1010 // 10
let b = 0b1100 // 12
let result = a & b // 8
Overflow Operators
Handle integer overflow safely
let max = UInt8.max // 255
let overflow = max &+ 1 // 0
Nil-Coalescing
Provide default values for optionals
let optional: String? = nil
let value = optional ?? "Default"
Range Operators
Create ranges of values
let range = 1...5 // 1,2,3,4,5
let halfOpen = 1..<5 // 1,2,3,4
🔹 Bitwise Operators
Bitwise operators work on the binary representation of numbers:
// Bitwise NOT (~) - flips all bits
let initialBits: UInt8 = 0b00001111 // 15
let invertedBits = ~initialBits // 11110000 (240)
print("NOT \(initialBits): \(invertedBits)")
// Bitwise AND (&) - 1 only if both bits are 1
let firstSixBits: UInt8 = 0b11111100 // 252
let lastSixBits: UInt8 = 0b00111111 // 63
let middleFourBits = firstSixBits & lastSixBits // 00111100 (60)
print("AND result: \(middleFourBits)")
// Bitwise OR (|) - 1 if either bit is 1
let someBits: UInt8 = 0b10110010 // 178
let moreBits: UInt8 = 0b01011110 // 94
let combinedbits = someBits | moreBits // 11111110 (254)
print("OR result: \(combinedbits)")
// Bitwise XOR (^) - 1 if bits are different
let firstBits: UInt8 = 0b00010100 // 20
let otherBits: UInt8 = 0b00000101 // 5
let outputBits = firstBits ^ otherBits // 00010001 (17)
print("XOR result: \(outputBits)")
Output:
NOT 15: 240
AND result: 60
OR result: 254
XOR result: 17
🔹 Bit Shifting Operators
Shift bits left or right to multiply or divide by powers of 2:
// Left shift (<<) - multiply by 2^n
let shiftBits: UInt8 = 4 // 00000100
let leftShift = shiftBits << 1 // 00001000 (8)
let leftShift2 = shiftBits << 2 // 00010000 (16)
print("4 << 1 = \(leftShift)")
print("4 << 2 = \(leftShift2)")
// Right shift (>>) - divide by 2^n
let rightShift = shiftBits >> 1 // 00000010 (2)
let rightShift2 = shiftBits >> 2 // 00000001 (1)
print("4 >> 1 = \(rightShift)")
print("4 >> 2 = \(rightShift2)")
// Practical example: Fast multiplication/division
func fastMultiplyBy8(_ number: Int) -> Int {
return number << 3 // Shift left by 3 positions (2^3 = 8)
}
func fastDivideBy4(_ number: Int) -> Int {
return number >> 2 // Shift right by 2 positions (2^2 = 4)
}
print("Fast multiply 5 by 8: \(fastMultiplyBy8(5))")
print("Fast divide 20 by 4: \(fastDivideBy4(20))")
Output:
4 << 1 = 8
4 << 2 = 16
4 >> 1 = 2
4 >> 2 = 1
Fast multiply 5 by 8: 40
Fast divide 20 by 4: 5
🔹 Overflow Operators
Handle integer overflow without crashing:
// Regular operators crash on overflow
// let overflow = UInt8.max + 1 // This would crash!
// Overflow addition (&+)
let maxValue = UInt8.max // 255
let overflowAdd = maxValue &+ 1 // Wraps to 0
print("255 &+ 1 = \(overflowAdd)")
// Overflow subtraction (&-)
let minValue = UInt8.min // 0
let overflowSub = minValue &- 1 // Wraps to 255
print("0 &- 1 = \(overflowSub)")
// Overflow multiplication (&*)
let largeNumber: UInt8 = 200
let overflowMul = largeNumber &* 2 // Wraps around
print("200 &* 2 = \(overflowMul)")
// Practical example: Circular buffer index
func nextIndex(current: UInt8, bufferSize: UInt8) -> UInt8 {
return (current &+ 1) % bufferSize
}
let currentIndex: UInt8 = 7
let bufferSize: UInt8 = 8
let next = nextIndex(current: currentIndex, bufferSize: bufferSize)
print("Next index after \(currentIndex): \(next)")
Output:
255 &+ 1 = 0
0 &- 1 = 255
200 &* 2 = 144
Next index after 7: 0
🔹 Nil-Coalescing Operator
The nil-coalescing operator (??) provides default values for optionals:
// Basic nil-coalescing
let optionalName: String? = nil
let userName = optionalName ?? "Anonymous"
print("User: \(userName)")
// With non-nil value
let optionalAge: Int? = 25
let userAge = optionalAge ?? 0
print("Age: \(userAge)")
// Chaining nil-coalescing
let firstName: String? = nil
let lastName: String? = nil
let nickname: String? = "Swift Learner"
let displayName = firstName ?? lastName ?? nickname ?? "Unknown"
print("Display name: \(displayName)")
// Function with optional return
func getUserPreference() -> String? {
// Simulate getting user preference
return nil
}
let theme = getUserPreference() ?? "light"
print("Theme: \(theme)")
// Practical example: Configuration with defaults
struct AppConfig {
let serverURL: String
let timeout: Int
let enableLogging: Bool
init(serverURL: String? = nil, timeout: Int? = nil, enableLogging: Bool? = nil) {
self.serverURL = serverURL ?? "https://api.example.com"
self.timeout = timeout ?? 30
self.enableLogging = enableLogging ?? false
}
}
let config = AppConfig(timeout: 60)
print("Server: \(config.serverURL), Timeout: \(config.timeout)s")
Output:
User: Anonymous
Age: 25
Display name: Swift Learner
Theme: light
Server: https://api.example.com, Timeout: 60s
🔹 Range Operators
Create ranges for loops, arrays, and collections:
// Closed range operator (...)
let closedRange = 1...5
print("Closed range includes:")
for number in closedRange {
print(number, terminator: " ")
}
print()
// Half-open range operator (..<)
let halfOpenRange = 1..<5
print("Half-open range includes:")
for number in halfOpenRange {
print(number, terminator: " ")
}
print()
// One-sided ranges
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// From index to end
let fromThree = numbers[3...]
print("From index 3: \(Array(fromThree))")
// From start to index
let upToFive = numbers[...5]
print("Up to index 5: \(Array(upToFive))")
// From start up to (but not including) index
let upToFour = numbers[..<4]
print("Up to index 4: \(Array(upToFour))")
// Practical example: String slicing
let text = "Hello, Swift!"
let startIndex = text.index(text.startIndex, offsetBy: 7)
let endIndex = text.index(text.startIndex, offsetBy: 12)
let substring = text[startIndex..<endIndex]
print("Substring: \(substring)")
Output:
Closed range includes:
1 2 3 4 5
Half-open range includes:
1 2 3 4
From index 3: [4, 5, 6, 7, 8, 9, 10]
Up to index 5: [1, 2, 3, 4, 5, 6]
Up to index 4: [1, 2, 3, 4]
Substring: Swift