Storyboard Identifier Exists

ID

swift.storyboard_id_exists

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Swift

Tags

reliability, suspicious-code

Description

Reports Swift call sites of UIStoryboard.instantiateViewController(withIdentifier:) (or the iOS 13+ instantiateViewController(identifier:) form) whose identifier literal is not declared by any <viewController storyboardIdentifier="…​"> element in the project’s .storyboard / .xib files. The Interface Builder runtime resolves the identifier when the call executes; an unknown name raises NSInvalidArgumentException and the app crashes on the first navigation to that scene.

let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "GhostVC")   // FLAW: not declared
let ok = sb.instantiateViewController(withIdentifier: "HomeVC")    // OK

Rationale

Storyboard identifiers are pure strings. Renaming a scene’s identifier in Interface Builder without updating Swift call sites — or vice versa — leaves a latent crash the compiler can’t catch. The defect typically surfaces in QA on the first navigation, or worse, in production when a rarely-used flow is finally exercised.

The rule collects every literal identifier passed to instantiateViewController across all Swift files, then walks every storyboard’s XML for storyboardIdentifier attributes and emits an issue for any call site whose literal doesn’t match a declared identifier.

Computed identifiers (variables, format strings, etc.) are skipped — the rule has no way to verify a value it can’t see at scan time. Projects with no storyboards at all are skipped too: those usually consume scenes from a binary framework or CocoaPod that’s outside the scan view.

Remediation

Either update the storyboard so the identifier matches the call site, or change the Swift literal to point at the declared identifier. Both fixes are one-character edits and the compiler validates neither — only this rule does.