Protocol in Swift is a contract that defines a set of requirements that any adopting type must satisfy. Protocols are the foundation of Protocol-Oriented Programming (POP) — a paradigm recommended by Apple for Swift alongside classical OOP. According to Apple Documentation, 2026, structures, classes, and enums can adopt protocols, making the architecture flexible and testable.
Key Takeaways
Protocol is an abstract interface that defines what a type must be able to do, but not how it does it. In Swift, a protocol is analogous to interfaces in Java or Go, but with additional capabilities.
A protocol can require:
{ get } or { get set } specifiersAccording to WWDC 2015, Apple introduced Protocol-Oriented Programming as a fundamental approach to Swift application architecture. Unlike OOP, where class inheritance creates rigid hierarchies, POP offers protocol composition. This provides flexibility: a single type can conform to multiple protocols, gaining their requirements and implementations through extensions.
Protocol is declared with the protocol keyword, a name, and a body.
protocol Drawable {
func draw(context: CGContext)
var boundingBox: CGRect { get }
}
A type adopts a protocol using a colon after its name:
struct Circle: Drawable {
let center: CGPoint
let radius: CGFloat
func draw(context: CGContext) {
context.addArc(center: center, radius: radius, ...)
}
var boundingBox: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
}
A single type can adopt multiple protocols separated by commas: struct MyType: ProtocolA, ProtocolB. The compiler verifies that all requirements of each protocol are fulfilled.
Property requirements are declared with the var keyword and access specifiers { get } or { get set }.
protocol UserProtocol {
var name: String { get }
var age: Int { get set }
static var maxAge: Int { get }
mutating func updateName(_ newName: String)
}
The mutating keyword in a protocol indicates that the method may modify self. Structures must implement such a method as mutating, while classes may omit it. Method requirements are declared with a full signature, including parameter labels.
Protocol can inherit another protocol, adding new requirements. This creates a hierarchy of contracts without rigid class coupling.
protocol Vehicle {
var speed: Double { get set }
func move()
}
protocol Flyable: Vehicle {
var altitude: Double { get set }
func takeOff()
}
A type adopting Flyable must fulfill the requirements of both protocols — Vehicle and Flyable. Swift supports multiple protocol inheritance: protocol A: B, C.
Protocol Composition is a mechanism that allows specifying that a type must conform to multiple protocols simultaneously, without creating a new combined protocol.
func render(_ item: Drawable & Animatable) {
item.draw(context: ...)
item.animate(duration: 0.3)
}
Composition (&) works in function parameters, variables, and generic constraints. The compiler verifies that the passed type simultaneously satisfies all protocols. Composition is widely used in SwiftUI: some View is a generic with composition.
Protocol Composition is preferable to creating an inheritance hierarchy: instead of protocol A: B, C, you can adopt B & C directly. This provides flexibility and reduces coupling. Composition is especially useful in function parameters and generic constraints where you need to temporarily combine requirements without creating an intermediate protocol. This reduces the number of auxiliary types in your code.
Protocol can be used as a type for a variable, function parameter, or collection element. This is called an existential type.
var drawableItem: Drawable
let items: [Drawable] = [Circle(...), Rectangle(...)]
func process(drawables: [any Drawable]) {
for item in drawables {
item.draw(context: ...)
}
}
The any keyword (Swift 5.6+) explicitly marks an existential. Without any, the compiler issues a warning. Swift also supports some (opaque types) for hiding the concrete type behind a protocol — this is a standard approach in SwiftUI.
When working with protocols, developers often make several recurring mistakes.
Drawable instead of <T: Drawable> where a concrete type is neededAnyObject unnecessarily, which excludes struct and enumFrequently Asked Questions
Protocol defines only requirements without implementation (until protocol extensions). An abstract class can contain implementation and state. Swift has no abstract classes — their role is fulfilled by protocols with extensions.
Yes, structures, classes, and enums can all adopt protocols. This is the foundation of POP: you don’t have to use classes to organize architecture. Structures with protocols provide value semantics and immutability.
Associated type (associatedtype) is a placeholder for a type that the implementing type determines itself. Example: Collection has associatedtype Element. This is a generic at the protocol level.
Yes, add inheritance from AnyObject: protocol MyProtocol: AnyObject. Then only classes can adopt this protocol. This is useful for weak references and delegates.
Use is for checking and as? for casting: if let drawable = item as? Drawable. This only works for protocols without associated types.
Summary
&) combines protocols without inheritanceany) and opaque types (some) — two ways to work with protocolsWe will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also