Class Delegate Protocol
ID |
swift.class_delegate_protocol |
Severity |
info |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Swift |
Tags |
delegation, reliability, retain_cycle |
Description
Reports a protocol whose name ends in Delegate or DataSource but
is not class-bound. Only a class-bound protocol (one that inherits
AnyObject, the modern Swift form of the : class requirement) can
be referenced through a weak or unowned property, which is the
standard way to break the retain cycle inherent to the Cocoa
delegation pattern.
protocol PlayerDelegate { // FLAW — could be a struct, no weak ref
func didFinish()
}
Rationale
A Cocoa-style delegate holds a back-reference to its owner. Without a
weak reference, owner and delegate keep each other alive forever —
the classic UIKit retain cycle. weak requires the referent to be a
class instance; if the protocol could be satisfied by a struct or
enum, the property cannot be weak, so callers are forced into
strong references and into manual cleanup. Making the protocol
class-bound shifts that constraint to where it belongs.
Remediation
Mark the protocol class-bound by inheriting AnyObject:
protocol PlayerDelegate: AnyObject {
func didFinish()
}
This is the complement of swift.weak_delegate_references, which
flags the property side (var delegate: PlayerDelegate missing
weak).