Marker
A Marker protocol has no requirements. Conformance communicates a category to generic code or the type system. Use it sparingly: an enum property is often clearer when the category is runtime data.
iOS use case
A router should open account and billing screens only after authentication. Public screens do not require this gate.
import Foundation
protocol AppRoute {
var path: String { get }
}
protocol ProtectedRoute: AppRoute {}
struct HelpRoute: AppRoute {
let path = "/help"
}
struct BillingRoute: ProtectedRoute {
let path = "/billing"
}
struct RouteGate {
let isSignedIn: Bool
func canOpen<R: AppRoute>(_ route: R) -> Bool {
!(route is any ProtectedRoute) || isSignedIn
}
}
let gate = RouteGate(isSignedIn: false)
let allowed = gate.canOpen(BillingRoute()) // falseThe marker makes protected routes distinguishable without adding the same Boolean to every route. The router checks it before navigation.
Production decisions
Do not treat a client-side route gate as authorization. The backend must enforce access to protected data. For a small finite route enum, a computed requiresAuthentication property may be simpler and more discoverable than marker protocols. Test deep links, sign-out during a protected flow, and restored navigation state.
What the empty protocol communicates
ProtectedRoute adds no methods or properties. Its sole purpose is to identify a subset of AppRoute values at the type level. RouteGate checks that conformance and requires sign-in before opening those routes. This is different from a Boolean property stored in every route instance: the classification comes from the route type itself and cannot vary per instance.
From example to an iOS router
When a deep link arrives, parse it into a route, run the gate, and then either navigate or start authentication. After sign-in, resume the pending route only if it is still valid for the current account. The same gate should be used for taps inside the app and external links so navigation behavior is consistent. Backend authorization remains mandatory; a client route marker only controls presentation.
Failure modes and verification
Test public routes, protected routes, deep links while signed out, and sign-out while already viewing protected content. Marker protocols can become invisible policy if developers forget to conform a new route. A finite route enum with an exhaustive requiresAuthentication switch may be safer because adding a case forces a decision. Choose the form that makes omissions easier to detect in your codebase.