Swift
programming
error-handling
Swift 1.2
iOS development

A declaration cannot be both 'final' and 'dynamic' error in Swift 1.2

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

This Swift error happens because final and dynamic ask the compiler to do opposite things. final says the declaration should not participate in override-based dynamic dispatch, while dynamic says dispatch should go through the Objective-C runtime dynamically. Swift rejects the combination because the two modifiers are fundamentally incompatible.

What final Means

When a class member is marked final, Swift knows it cannot be overridden in a subclass. That gives the compiler freedom to use direct dispatch and other optimizations.

For example:

swift
1class BaseController {
2    final func render() {
3        print("render")
4    }
5}

Here render is fixed. Subclasses may inherit it, but they cannot override it.

What dynamic Means

dynamic tells Swift to use Objective-C-style dynamic dispatch for that declaration. It is usually associated with cases where runtime behavior matters, such as:

  • KVO
  • method swizzling
  • Objective-C runtime messaging

For example:

swift
1import Foundation
2
3class Person: NSObject {
4    @objc dynamic var name: String = ""
5}

The dynamic behavior is specifically about runtime message dispatch, not compile-time locking of the implementation.

Why the Two Keywords Conflict

Now consider this invalid declaration:

swift
1class Example: NSObject {
2    @objc dynamic final func update() {
3        print("update")
4    }
5}

Swift rejects it because:

  • 'final says no runtime override-style flexibility is needed'
  • 'dynamic says route this through dynamic Objective-C dispatch'

You are asking for both less dynamism and more dynamism at the same time. The compiler cannot satisfy both intent signals meaningfully, so it reports the error.

Choose the Modifier That Matches the Real Requirement

If the declaration must support Objective-C runtime features, use dynamic and remove final:

swift
1import Foundation
2
3class Example: NSObject {
4    @objc dynamic func update() {
5        print("update")
6    }
7}

If the real goal is to prevent overriding and keep dispatch as direct as possible, use final and remove dynamic:

swift
1class Example {
2    final func update() {
3        print("update")
4    }
5}

The right answer depends on why the declaration had those modifiers in the first place.

Common Real-World Cases

For KVO or Objective-C runtime integration, dynamic is usually the one you actually need. For internal Swift-only methods where you want to lock down behavior and communicate intent, final is usually the better choice.

This often shows up during refactoring. A developer may add final broadly for design or performance reasons and later add dynamic for runtime behavior without realizing the two are incompatible.

Do Not Optimize Blindly

Historically, some developers added final aggressively because they wanted performance improvements. Others added dynamic because an Objective-C feature seemed to require it. In both cases, the modifier should reflect a real semantic need, not a cargo-cult rule.

If you are working in Swift-only code with no runtime magic involved, dynamic is usually unnecessary. If you need Objective-C runtime participation, then final is usually the wrong modifier for that declaration.

Common Pitfalls

The most common mistake is assuming final and dynamic are both “good” modifiers and can therefore be combined. They are not additive in that way.

Another pitfall is forgetting that dynamic is tied to runtime dispatch semantics rather than normal Swift method calls. If the code does not need Objective-C runtime behavior, dynamic is often the wrong tool.

It is also easy to over-apply final during refactors and then hit this error only later when a property or method needs KVO or similar runtime behavior.

Finally, do not pick a modifier only because of a vague performance or interoperability instinct. Start from the actual requirement and the correct modifier usually becomes obvious.

Summary

  • 'final and dynamic conflict because they express opposite dispatch intentions.'
  • Use final when you want to prevent overriding and keep the declaration fixed.
  • Use dynamic when Objective-C runtime dispatch is required.
  • Remove one of the modifiers based on the real semantic need.
  • This is a design conflict in the declaration, not a strange Swift parser bug.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Basis Lab
No course covers this one yet

Basis Lab writes one for you from a sentence about what you want to be able to do, then teaches it and checks you understood. Your first course is free.

Build my course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions