Functional or OOP in Swift: What to Choose for an iOS Project?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Two Sides of the Same Coin: Functional vs Object-Oriented Approach in Swift

\n\n

When I first started writing for iOS, I thought that object-oriented programming was the only right way. Classes, inheritance, polymorphism — it all sounded like a developer's holy scripture. But then I discovered functional programming in Swift, and my world turned upside down. It turns out you can write code that doesn't mutate state, that is easy to test, and that looks like a mathematical formula.

\n\n

Swift is a unique language. It is multi-paradigm. This means you can mix OOP and the functional approach in one project, taking the best from both worlds. But how do you avoid confusion? When to use classes, and when to use closures and map? Let's figure it out.

\n\n

Object-Oriented Swift: A Classic That Works

\n\n

Object-oriented programming (OOP) in Swift is built around classes, protocols, and inheritance. It is a paradigm where data and behavior live together. You create a model — for example, a "User" — and this object itself knows how to introduce itself, how to change its name, or calculate its age.

\n\n

Here is a classic example in Swift:

\n\n
class User {\n    var name: String\n    var age: Int\n    \n    init(name: String, age: Int) {\n        self.name = name\n        self.age = age\n    }\n    \n    func greet() -> String {\n        return "Hello, my name is \\(name) and I am \\(age) years old."\n    }\n    \n    func haveBirthday() {\n        age += 1\n    }\n}\n\nlet user = User(name: "Anna", age: 25)\nuser.haveBirthday()\nprint(user.greet()) // Hello, my name is Anna and I am 26 years old.
\n\n

In this code, we use the object-oriented approach in Swift. We have state (properties name, age) that can change (method haveBirthday). This is intuitive, especially if you come from Java or C++. But there is a nuance: mutable state is a source of bugs. The more objects change each other, the harder it is to debug the program.

\n\n

Functional Swift: The Power of Closures and Immutability

\n\n

Functional programming in Swift offers a different perspective. Here, functions are "first-class citizens." You can pass them as parameters, return them from other functions, and store them in variables. The main principle is pure functions, which do not change external state and always return the same result for the same input data.

\n\n

Let's see how the same example looks in a functional style:

\n\n
struct User {\n    let name: String\n    let age: Int\n}\n\nfunc greet(user: User) -> String {\n    return "Hello, my name is \\(user.name) and I am \\(user.age) years old."\n}\n\nfunc haveBirthday(user: User) -> User {\n    return User(name: user.name, age: user.age + 1)\n}\n\nlet user = User(name: "Anna", age: 25)\nlet olderUser = haveBirthday(user: user)\nprint(greet(user: olderUser)) // Hello, my name is Anna and I am 26 years old.
\n\n

Notice: we use a struct, not a class. Structs in Swift are value types. They are copied upon assignment. The function haveBirthday does not mutate the original object; it creates a new one. This is the key idea of the functional approach — immutability.

\n\n

Comparison of Approaches: When to Use What?

\n\n

Now let's honestly compare OOP and functional programming in Swift. Each has its strengths.

\n\n

Object-Oriented Approach in Swift

\n\n
    \n
  • Pros: Intuitive for modeling the real world. Great for UI components (UIViewController, UIView). Inheritance simplifies code reuse.
  • \n
  • Cons: Mutable

Blogs

Book Recommendations