Course

Swift Protocol: Syntax, Usage, and Examples

A Swift protocol defines a blueprint of methods, properties, and other requirements that classes, structures, and enumerations must adopt. Protocols let you define shared functionality without requiring inheritance, making them a key part of protocol-oriented programming in Swift.

How to Use Protocols in Swift

To define a protocol, use the protocol keyword, then list the required properties and methods. Any type that conforms to the protocol must implement these requirements.

swift
protocol Greetable { var name: String { get } func greet() } struct Person: Greetable { var name: String func greet() { print("Hello, my name is \(name).") } } let john = Person(name: "John") john.greet() // Output: Hello, my name is John.

Here, Greetable is a Swift protocol that requires a name property and a greet method. The Person struct conforms to the protocol by implementing both.

Protocol Properties

Protocols define protocol properties in Swift that conforming types must provide. These can be read-only ({ get }) or read-write ({ get set }).

swift
protocol Vehicle { var speed: Int { get set } var capacity: Int { get } }

Protocol Methods

Protocols can define methods without providing an implementation. Any type conforming to the protocol must implement these methods.

swift
protocol Drivable { func start() func stop() } class Car: Drivable { func start() { print("Car is starting...") } func stop() { print("Car is stopping...") } }

When to Use Protocols in Swift

Standardizing Behavior

Protocols help define a standard behavior across multiple types without forcing them into a class hierarchy.

swift
protocol Flyable { func fly() } struct Bird: Flyable { func fly() { print("The bird is flying.") } } struct Plane: Flyable { func fly() { print("The plane is flying.") } }

Creating Flexible Code

You can use protocol-oriented programming in Swift to make your code more flexible by defining shared behavior that multiple unrelated types can adopt.

swift
protocol Storable { func save() } class Document: Storable { func save() { print("Saving document...") } } class Image: Storable { func save() { print("Saving image...") } }

Supporting Delegation

Protocols are commonly used for delegation, allowing one object to pass responsibility to another.

swift
protocol DownloadDelegate { func didFinishDownloading() } class Downloader { var delegate: DownloadDelegate? func download() { print("Downloading...") delegate?.didFinishDownloading() } } class ViewController: DownloadDelegate { func didFinishDownloading() { print("Download complete!") } } let vc = ViewController() let downloader = Downloader() downloader.delegate = vc downloader.download() // Output: // Downloading... // Download complete!

Examples of Protocols in Swift

Using a Protocol with an Array

You can store different types in an array as long as they conform to the same protocol.

swift
protocol Animal { func makeSound() } struct Dog: Animal { func makeSound() { print("Woof!") } } struct Cat: Animal { func makeSound() { print("Meow!") } } let animals: [Animal] = [Dog(), Cat()] animals.forEach { $0.makeSound() } // Output: // Woof! // Meow!

Extending Protocols

A Swift protocol extension allows you to add default implementations for protocol methods.

swift
protocol Identifiable { var id: String { get } } extension Identifiable { func identify() { print("My ID is \(id).") } } struct User: Identifiable { var id: String } let user = User(id: "123") user.identify() // Output: My ID is 123.

Using Generics with Protocols

A Swift generic protocol allows you to define flexible and reusable code that works with multiple types.

swift
protocol Storage { associatedtype Item func store(_ item: Item) } class Box<T>: Storage { typealias Item = T func store(_ item: T) { print("Storing \(item)") } } let intBox = Box<Int>() intBox.store(42) // Output: Storing 42

Protocol Inheritance

A protocol can inherit from one or more protocols using a comma-separated list.

swift
protocol Movable { func move() } protocol Stoppable { func stop() } protocol Vehicle: Movable, Stoppable {} class Bicycle: Vehicle { func move() { print("Bicycle is moving.") } func stop() { print("Bicycle is stopping.") } } let bike = Bicycle() bike.move() // Output: Bicycle is moving. bike.stop() // Output: Bicycle is stopping.

Learn More About Protocols in Swift

Class-Only Protocols

You can restrict a protocol to class-only types using AnyObject.

swift
protocol ViewControllerDelegate: AnyObject { func didUpdate() }

Optional Protocol Methods

Swift doesn’t support optional protocol methods directly, but you can work around this using @objc and optional.

swift
@objc protocol OptionalProtocol { @objc optional func optionalMethod() }

Protocol vs. Class

  • Protocols allow multiple types to share behavior without inheritance.
  • Classes enforce a strict hierarchy where child classes inherit from a parent.
  • Use protocols when defining behavior that multiple unrelated types should conform to.
  • Use classes when modeling relationships where objects need shared state and behavior.

Protocol-Oriented Programming vs. Object-Oriented Programming

  • Object-Oriented Programming (OOP) relies on classes and inheritance.
  • Protocol-Oriented Programming (POP) promotes composition over inheritance, leading to more modular and testable code.

Using Protocols in Real-World Projects

Protocols are widely used in SwiftUI, UIKit, and networking. You often see them in delegate patterns, custom UI components, and dependency injection.

Example: Networking with a Protocol

swift
protocol NetworkService { func fetchData(from url: String) } class APIClient: NetworkService { func fetchData(from url: String) { print("Fetching data from \(url)") } } let apiClient: NetworkService = APIClient() apiClient.fetchData(from: "https://example.com") // Output: Fetching data from https://example.com

Best Practices for Using Protocols in Swift

  • Use protocols instead of inheritance when possible. They make your code more flexible and reusable.
  • Define small, focused protocols. Avoid protocols with too many responsibilities.
  • Use protocol extensions to provide default implementations.
  • Avoid forcing class inheritance unless necessary. Use protocol-oriented programming when structuring your app.
  • Prefer composition over inheritance. Instead of creating deep class hierarchies, break functionality into separate protocols.