DEV Community

Harsh Prajapat
Harsh Prajapat

Posted on

Read Blog

To run a reverse for loop in Swift, the cleanest and most common approach is to use the .reversed() method on a range or a collection.

1. Reverse Loop Over a Number Range

To count downwards between two numbers, wrap your range in parentheses and append .reversed():

// Counts down from 5 to 1 inclusive
for index in (1...5).reversed() {
    print(index) 
}
// Output: 5, 4, 3, 2, 1
Enter fullscreen mode Exit fullscreen mode
// Counts down from 4 to 0 (excludes the upper bound 5)
for index in (0..<5).reversed() {
    print(index)
}
// Output: 4, 3, 2, 1, 0
Enter fullscreen mode Exit fullscreen mode

2. Reverse Loop Over an Array

let items = ["Apple", "Banana", "Cherry"]

for item in items.reversed() {
    print(item)
}
// Output: Cherry, Banana, Apple
Enter fullscreen mode Exit fullscreen mode

3. Reverse Loop with Index and Value

If you need both the index and the element while going backward, combine .reversed() with .enumerated().

let names = ["Alex", "Brian", "Chris"]

for (index, name) in names.reversed().enumerated() {
    print("Index \(index) contains \(name)")
}
// Output: 
// Index 2 contains Chris
// Index 1 contains Brian
// Index 0 contains Alex
Enter fullscreen mode Exit fullscreen mode

4. Reverse Loop with Custom Step Sizes (stride)

// Inclusive stride
for index in stride(from: 10, through: 0, by: -2) {
    print(index)
}
// Output: 10, 8, 6, 4, 2, 0
Enter fullscreen mode Exit fullscreen mode

What is compile time and runtime error

The core difference is that compile-time errors prevent your program from building, while runtime errors occur while the program is executing.

Compile-Time Error:

During code compilation (before running).
Prevent an executable from being created.

Runtime Error:

During program execution.
Program crashes or behaves unpredictably.

A generic function in Swift allows you to write flexible, reusable code that can work with any data type while maintaining complete type safety. Instead of duplicating logic for Int, String, or Double, you use a placeholder type (conventionally named T) inside angle brackets ().

Basic Syntax

// Defining a generic function with a placeholder type T
func printValue<T>(_ value: T) {
    print("The value is: \(value)")
}

// Swift automatically infers the concrete type at runtime
printValue(42)        // T becomes Int
printValue("Hello")   // T becomes String
printValue(3.14)      // T becomes Double
Enter fullscreen mode Exit fullscreen mode

In Swift, the Comparable protocol is used to define a natural relational order for instances of a type. Conforming to Comparable allows you to use relational operators like <, >, <=, and >=, and unlocks standard library capabilities like sorting an array with a parameterless .sorted() method.

func findLargest(_ a: T, _ b: T) -> T {
return a > b ? a : b
}

let highestScore = findLargest(85, 92) // Works with Int
let alphabetLast = findLargest("apple", "banana")

print(highestScore) // 85
print(alphabetLast) // banana

In Swift, subscripts are shortcuts used to access or modify member elements of a collection, list, or sequence without explicitly calling a method. They allow you to use bracket notation like instance[index] directly on your custom classes, structures, and enumerations.

Subscript declarations resemble a mix of instance methods and computed properties. They are defined using the subscript keyword, taking input parameters and specifying a return type.

struct SimpleList {
    var items: [String]

    // Read-and-Write Subscript
    subscript(index: Int) -> String {
        get {
            return items[index]
        }
        set(newValue) {
            items[index] = newValue
        }
    }
}

struct Multiplier {
    let factor: Int

    // Read-only shortcut
    subscript(number: Int) -> Int {
        return number * factor
    }
}

let threeTimes = Multiplier(factor: 3)
print(threeTimes[6]) // Prints 18
Enter fullscreen mode Exit fullscreen mode

Safe Array Access

extension Array {
subscript(safe index: Int) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}

let names = ["Alice", "Bob"]
print(names[safe: 5]) // Prints nil (No runtime crash!)

why Functional Programming swift explain

Functional Programming (FP) in Swift is a paradigm that treats computation as the evaluation of mathematical functions, heavily emphasizing immutability and preventing state changes. Swift is designed from the ground up as a multi-paradigm language, meaning it natively blends Object-Oriented Programming (OOP) with powerful, built-in features for Functional Programming.

Implementing functional patterns in Swift eliminates hidden side effects, ensures inherent thread safety, and dramatically simplifies unit testing.

Core Concepts of Functional Swift

  1. Immutability & Value Types

let over var: Using let guarantees that data cannot be modified after creation, removing unexpected state changes.

Value Types (Structs and Enums): Unlike classes (which are reference types), structs are passed by value. When passed to a function, Swift copies the data, ensuring other parts of the app cannot accidentally overwrite it.

  1. First-Class and Higher-Order Functions

Functions that accept or return other functions are known as Higher-Order Functions. The Swift Standard Library natively includes several higher-order tools to process data without using manual loops:

map: Transforms every item in a collection.
filter: Extracts items matching specific conditions.
reduce: Combines all elements into a single value.

let numbers = [1, 2, 3, 4, 5]

// Declarative functional chain vs. Imperial "for" loop
let doubledEvens = numbers
    .filter { $0 % 2 == 0 }  // Filters out odd numbers
    .map { $0 * 2 }
Enter fullscreen mode Exit fullscreen mode

can we use lazy let in swift instead of lazy var

No, you cannot use lazy let in Swift. Swift strictly requires you to use lazy var

The Swift compiler will throw a compile-time error if you attempt to use lazy let.

Why Swift Doesn't Allow lazy let

If your goal is to make sure a lazy property cannot be modified by other parts of your code after it initializes, you can use the private(set) modifier.

class DataManager {
    // Read-only to the outside world, but mutates internally on first access
    private(set) lazy var expensiveData: [String] = {
        print("Loading heavy data...")
        return ["Data 1", "Data 2", "Data 3"]
    }()
}

let manager = DataManager()
// 1. Works perfectly and triggers initialization
print(manager.expensiveData) 

// 2. Compiler Error: Cannot assign to property: 'expensiveData' setter is inaccessible
manager.expensiveData = ["New Data"] 
Enter fullscreen mode Exit fullscreen mode

in unowned can we use let or var both swift

The choice between let and var purely depends on whether you want the reference itself to be mutable (re-assignable) or immutable (constant). This is a major structural advantage over weak, which must always be declared as a var because Automated Reference Counting (ARC) dynamically zeroes it out to nil when the referenced instance deallocates.

Using unowned let

Use unowned let when the reference is assigned exactly once during initialization and never changes.

It creates an immutable binding between an object and its non-strong dependency.

class Customer {
    let name: String
    init(name: String) { self.name = name }
}

class CreditCard {
    let number: UInt64
    // The owner never changes, but we don't want a strong reference cycle
    unowned let owner: Customer 

    init(number: UInt64, owner: Customer) {
        self.number = number
        self.owner = owner
    }
}
Enter fullscreen mode Exit fullscreen mode

throw vs throws in swift ios

In Swift, throws is used in a function's declaration to signal that it can potentially fail, while throw is the action keyword used inside the function to execute and raise a specific error.

throws

Declares that a method, closure, or property can encounter and propagate a failure.

**Example

func check(id: Int) throws -> Bool**

throw

Triggers the actual failure, immediately halting execution and passing the error out.

**Example

throw NetworkError.timeout**

Implementation Example

To use error handling in iOS development, you must first define an enum that conforms to Swift's standard Error protocol.

// 1. Define your error types
enum ValidationError: Error {
    case emptyUsername
    case textTooShort
}

// 2. Use 'throws' in the signature to designate a throwing function
func validate(username: String) throws -> Bool {
    guard !username.isEmpty else {
        // 3. Use 'throw' to explicitly raise the error state
        throw ValidationError.emptyUsername 
    }

    guard username.count >= 3 else {
        throw ValidationError.textTooShort
    }

    return true
}
Enter fullscreen mode Exit fullscreen mode

H*ow to Call a Throwing Function*

When a function is marked with throws, the Swift compiler prevents you from executing it normally. You must handle it using a do-catch block combined with the try keyword:

do {
    let isValid = try validate(username: "Al")
    print("Success: \(isValid)")
} catch ValidationError.emptyUsername {
    print("Please enter a username.")
} catch ValidationError.textTooShort {
    print("Username must be at least 3 characters.")
} catch {
    print("An unknown error occurred: \(error).")
}
Enter fullscreen mode Exit fullscreen mode

In Swift, a standard parameter is a read-only copy. An inout parameter allows a function to modify the original variable directly.

Without inout (Copy)

var score = 10

func addBonus(points: Int) {
    // points is a copy. 
    // Changing it here does not affect 'score'.
    points += 5 
}

addBonus(points: score)
print(score) // Output: 10
Enter fullscreen mode Exit fullscreen mode

With inout (Reference)

To use inout:

  • You must declare the original variable using var (not let).
  • You must add the inout keyword before the parameter type.
  • You must put an ampersand (&) before the variable name when you call the function.
var score = 10

// 1. Mark the parameter as inout
func addBonus(points: inout Int) {
    // 2. Modifying it updates the original variable
    points += 5 
}

// 3. Put & before the variable when calling
addBonus(points: &score)
print(score) // Output: 15
Enter fullscreen mode Exit fullscreen mode

in swift can we Inheritance with Structures

No, structures in Swift do not support inheritance. In Swift, inheritance is a feature exclusive to classes. A struct cannot inherit from another struct or class, nor can it serve as a base type for another structure to inherit from.

Instead of classical inheritance, Swift relies heavily on Protocol-Oriented Programming and Composition to share behavior among structures

AssociatedType

protocol Container {

    associatedtype Item

    mutating func add(_ item: Item)

    func getItem() -> Item
}

struct IntContainer: Container {

    var value = 0

    mutating func add(_ item: Int) {
        value = item
    }

    func getItem() -> Int {
        value
    }
}

var container = IntContainer()

container.add(100)

print(container.getItem())
Enter fullscreen mode Exit fullscreen mode

Top comments (0)