Swiftで同じ名前のVariable、Property、Function、Type、Enum Caseなどを重複して定義すると、Xcodeに次のようなErrorが表示されることがあります。
Invalid redeclaration of 'name'
例えば:
Invalid redeclaration of 'ContentView'
や:
Invalid redeclaration of 'viewDidLoad()'
などです。
このErrorは、同じScopeや同じModule内で、Compilerから見て区別できないDeclarationが複数存在している場合に発生します。
代表的な原因は、同じClassやStructを2回定義した、同名Propertyを重複して書いた、同じSignatureのFunctionを複数作った、Extensionと本体で同じMemberを定義した、FileをCopyした際に古いSourceがTargetへ残っている、Generated Codeと手書きCodeが衝突している、といったものです。
解決するときは、Errorが表示された行だけを見るのではなく、同じ名前・同じSignatureのDeclarationがProject内のどこに重複しているかを検索し、どちらを残すべきか判断することが重要です。
- 「Invalid redeclaration」とは
- なぜ同名Functionを作れる場合と作れない場合があるのか
- 代表的な発生状況
- 主な原因
- 1. 同じVariableを同一Scopeで2回宣言している
- 2. Class内で同じPropertyを2回宣言している
- 3. Struct内で同じPropertyを重複している
- 4. 同じFunction Signatureを複数定義している
- 5. Return Typeだけを変えてOverloadしようとしている
- 6. 同じClassを別Fileで定義している
- 7. SwiftUIのContentViewを複数作った
- 8. Extensionで同じPropertyやMethodを定義している
- 9. 複数Extensionで同じMethodを定義している
- 10. Global Functionを複数Fileへ定義している
- 11. Enum Caseを重複している
- 12. TypealiasとType名が衝突している
- 13. Protocol名と別Type名が衝突している
- 14. Nested Typeを重複している
- 15. IBOutlet Propertyを重複して追加した
- 16. IBAction Methodを重複している
- 17. File Copy後に同じDeclarationが残っている
- 18. Generated Codeと手書きCodeが衝突している
- 19. Core DataのCodegen設定と手書きClassが重複している
- 20. Merge Conflict解消時に同じCodeを2回残した
- まず確認すること
- 解決方法1:重複Declarationを削除する
- 解決方法2:別の意味を持つ値なら名前を変更する
- 解決方法3:Function Nameを変更する
- 解決方法4:正しくOverloadする
- 解決方法5:Argument Labelを変えて区別する
- 解決方法6:同名Typeの片方をRenameする
- 解決方法7:CopyしたFileのClass Nameを変更する
- 解決方法8:不要なCopy FileをTargetから外す
- 解決方法9:Backup FileはProject外へ移動する
- 解決方法10:Extension内の重複Methodを削除する
- 解決方法11:本体とExtensionの責務を分ける
- 解決方法12:SwiftUIのContentView重複を解消する
- 解決方法13:Preview用Viewと本番ViewのNameを分ける
- 解決方法14:Enum Caseの重複を削除する
- 解決方法15:TypealiasのNameを変更する
- 解決方法16:ProtocolとConcrete TypeのNameを分ける
- 解決方法17:IBActionやIBOutletの重複を削除する
- 解決方法18:Core DataのCodegen設定を確認する
- 解決方法19:Generated Sourceを確認する
- 解決方法20:同じGenerated Fileを2回Compileしていないか確認する
- 解決方法21:Compile Sourcesの重複や不要Fileを確認する
- 解決方法22:Target Membershipを確認する
- 解決方法23:同じModule内のGlobal Declarationを検索する
- 解決方法24:Nested TypeのNameを変更する
- 解決方法25:Merge Conflict後の重複Codeを確認する
- 解決方法26:OverloadのSignatureを意図的に区別する
- 解決方法27:Argument LabelでAPIの意味を分ける
- 解決方法28:同名PropertyをComputed PropertyとStored Propertyで重複させない
- 解決方法29:同名MethodとPropertyの衝突を確認する
- 解決方法30:XcodeのProject SearchでDeclarationを絞り込む
- SwiftUIで「Invalid redeclaration」が出る場合
- ClassやStructで発生する場合
- Functionで発生する場合
- Extensionで発生する場合
- Core Dataで発生する場合
- 「Project内に1つしかないはず」なのに出る場合
- Clean Build Folderで直るか
- DerivedData削除は必要か
- やってはいけない対処
- 最短で確認するチェックリスト
- まとめ
「Invalid redeclaration」とは
redeclarationは「再宣言」という意味です。
例えば:
let title = "Hello" let title = "World"
同じScopeでtitleを2回DeclarationしているためErrorになります。
同様に:
struct User { }
struct User {
}
のように同じType名を重複して定義しても:
Invalid redeclaration of 'User'
となります。
なぜ同名Functionを作れる場合と作れない場合があるのか
SwiftはFunction Overloadをサポートしています。
例えば:
func show(value: String) { }
func show(value: Int) {
}
はParameter Typeが異なるため別Functionとして区別できます。
一方:
func show(value: String) { }
func show(value: String) {
}
は完全に同じSignatureなので区別できずInvalid redeclarationになります。
ポイント:名前が同じでもCompilerがSignatureで区別できればOverloadとして成立します。区別できないDeclarationを重複させるとInvalid redeclarationになります。
代表的な発生状況
- 同じVariableを2回定義した
- 同じPropertyをClassやStruct内へ2回書いた
- 同じFunction Signatureを複数定義した
- 同じClassやStructを別Fileでも定義した
- 同じEnumを重複定義した
- 同じEnum Caseを重複させた
- Extensionと本体で同じMemberを定義した
- 同じProtocol Extensionを重複させた
- SwiftUIのContentViewを複数Fileで定義した
- FileをCopyした後、元FileとCopy Fileの両方がTargetに含まれている
- 旧Source Fileを削除したつもりでもTarget Membershipに残っている
- Generated Codeと手書きCodeが同じTypeやPropertyを生成している
- Core DataのClass Generationと手書きNSManagedObject Subclassが衝突している
- 同じIBActionやIBOutlet Propertyを重複して定義した
- 同じGlobal Functionを複数Fileへ書いた
主な原因
1. 同じVariableを同一Scopeで2回宣言している
let count = 10 let count = 20
同じScopeでは同名Variableを再Declarationできません。
2. Class内で同じPropertyを2回宣言している
final class UserViewModel { var name = "" var name = "" }
nameが重複しています。
3. Struct内で同じPropertyを重複している
struct User { let id: Int let id: Int }
4. 同じFunction Signatureを複数定義している
func save(name: String) { }
func save(name: String) {
}
Function Name、Argument Label、Parameter Typeなどから区別できません。
5. Return Typeだけを変えてOverloadしようとしている
例えば:
func load() -> String { "Hello" }
func load() -> Int {
10
}
Call SiteのContextによって区別できる場面もありますが、API Designとして曖昧になりやすく、同じDeclarationとして問題になる構成があります。
ParameterやFunction Nameなど、Call Siteから明確に区別できる設計にする方が安全です。
6. 同じClassを別Fileで定義している
例えば:
// User.swift final class User { }
別Fileにも:
// UserCopy.swift final class User { }
があると、同じModule内では重複します。
7. SwiftUIのContentViewを複数作った
Project Templateの:
struct ContentView: View { var body: some View { Text("Hello") } }
を残したまま、別Fileへ同名ContentViewを作るとErrorになります。
8. Extensionで同じPropertyやMethodを定義している
struct User { func displayName() -> String { "User" } }
extension User {
func displayName() -> String {
"User"
}
}
9. 複数Extensionで同じMethodを定義している
extension User { func reset() { } }
extension User {
func reset() {
}
}
10. Global Functionを複数Fileへ定義している
同一Module内のTop-level Declarationは別Fileにあっても衝突することがあります。
11. Enum Caseを重複している
enum Status { case active case inactive case active }
12. TypealiasとType名が衝突している
struct User { }
typealias User = String
同じScopeで同名Typeとして扱えない構成になります。
13. Protocol名と別Type名が衝突している
protocol Downloadable { }
struct Downloadable {
}
同一Scope内でType Nameが衝突します。
14. Nested Typeを重複している
struct Container { struct Item { }
struct Item {
}
}
15. IBOutlet Propertyを重複して追加した
@IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var titleLabel: UILabel!
16. IBAction Methodを重複している
@IBAction func didTapButton(_ sender: UIButton) { }
@IBAction func didTapButton(_ sender: UIButton) {
}
17. File Copy後に同じDeclarationが残っている
ViewController.swiftをCopyして名前だけFile側で変更し、内部のClass Nameを変更し忘れるケースです。
// HomeViewController.swift final class HomeViewController: UIViewController { }
// HomeViewControllerCopy.swift
final class HomeViewController: UIViewController {
}
18. Generated Codeと手書きCodeが衝突している
Code GeneratorやBuild Toolが生成したTypeを、自分でも同じ名前で定義している場合があります。
19. Core DataのCodegen設定と手書きClassが重複している
Core Data EntityでClass Definitionなどの自動生成を有効にしたまま、同じNSManagedObject Subclassを手書きするとDuplicate Typeが発生する場合があります。
20. Merge Conflict解消時に同じCodeを2回残した
Git Merge後に、似たDeclarationを両方残してしまうケースがあります。
まず確認すること
1. Error Messageに表示された名前をProject全体で検索する
例えば:
Invalid redeclaration of 'User'
なら、XcodeのProject Searchで:
User
を検索します。
より絞り込むなら:
struct User class User enum User typealias User
などを探します。
2. 同じFile内だけでなくProject全体を見る
Declarationは別Fileに存在していても同じModuleなら衝突する場合があります。
重要:Errorが出たFile内に重複が見つからない場合、別File、Extension、Generated Source、Target Membershipを確認してください。
3. FunctionならSignature全体を比較する
例えば:
func update( name: String, age: Int )
と同一のFunctionが別の場所にないか確認します。
解決方法1:重複Declarationを削除する
最も基本的な修正です。
問題:
let title = "Hello" let title = "World"
修正:
let title = "Hello"
不要な方を削除します。
解決方法2:別の意味を持つ値なら名前を変更する
let pageTitle = "Hello" let buttonTitle = "Continue"
役割が違うなら、意味を表す別名にします。
解決方法3:Function Nameを変更する
同じSignatureで処理内容が異なるなら:
func saveUser( name: String ) { }
func cacheUser(
name: String
) {
}
のように意図が分かるNameへ変更します。
解決方法4:正しくOverloadする
同じFunction Nameを使いたい場合は、Compilerが区別できるSignatureにします。
func show( value: String ) { }
func show(
value: Int
) {
}
Parameter Typeが異なるためOverloadとして利用できます。
解決方法5:Argument Labelを変えて区別する
func load( id: Int ) { }
func load(
index: Int
) {
}
Call Siteが:
load(id: 10) load(index: 10)
のように区別できる設計ならOverloadとして成立する場合があります。
解決方法6:同名Typeの片方をRenameする
例えば:
struct User { }
と:
struct APIUser { }
のように、Domain ModelとAPI Modelを別Nameにします。
解決方法7:CopyしたFileのClass Nameを変更する
FileをDuplicateした場合、File Nameだけでなく内部のType Nameも変更してください。
final class SettingsViewController: UIViewController { }
のように、新しい役割に合わせたNameへ変更します。
解決方法8:不要なCopy FileをTargetから外す
同じSourceを一時BackupとしてProjectへ置いている場合、そのFileがApp Targetへ含まれているとCompile対象になります。
XcodeのFile Inspectorで:
Target Membership
を確認し、Build対象に不要なFileなら対象Targetから外します。
解決方法9:Backup FileはProject外へ移動する
例えば:
ContentView_old.swift ContentView_copy.swift ViewController_backup.swift
のようなBackup SourceをProjectへ追加したままにすると、内部Declarationが同じ場合に衝突します。
Version Controlを利用し、不要なSource CopyはCompile対象から除外する方が安全です。
解決方法10:Extension内の重複Methodを削除する
問題:
extension User { func reset() { } }
extension User {
func reset() {
}
}
どちらか一方だけを残します。
解決方法11:本体とExtensionの責務を分ける
例えば、本体:
struct User { let name: String }
Extension:
extension User { var displayName: String { name.uppercased() } }
のようにMemberが重複しないよう整理します。
解決方法12:SwiftUIのContentView重複を解消する
Project全体から:
struct ContentView: View
を検索します。
複数見つかったら、不要な方を削除するか:
struct SettingsView: View { var body: some View { Text("Settings") } }
のように別Nameへ変更します。
解決方法13:Preview用Viewと本番ViewのNameを分ける
Preview検証用に別Viewを作る場合:
struct ContentViewPreviewSample: View { var body: some View { ContentView() } }
など、既存Typeと衝突しないNameを使用します。
解決方法14:Enum Caseの重複を削除する
問題:
enum Status { case active case inactive case active }
修正:
enum Status { case active case inactive }
解決方法15:TypealiasのNameを変更する
Type Nameと衝突している場合:
struct User { }
typealias UserName = String
のように別Nameへ変更します。
解決方法16:ProtocolとConcrete TypeのNameを分ける
例えば:
protocol Downloading { func download() }
final class Downloader:
Downloading {
func download() {
}
}
のように役割が分かるNameにします。
解決方法17:IBActionやIBOutletの重複を削除する
StoryboardからControl-dragを繰り返した結果、同じPropertyやMethodを複製していないか確認します。
@IBOutlet weak var titleLabel: UILabel!
は通常1つだけで十分です。
解決方法18:Core DataのCodegen設定を確認する
Core Data Entityで自動Class生成を使っている場合、同じEntity用のNSManagedObject Subclassを手書きすると重複することがあります。
Data Model InspectorでEntityの:
Codegen
設定を確認してください。
自動生成を利用するのか、Manual/Noneで手書きClassを管理するのかを統一します。
注意:Core Data関連の生成方式はProject構成によって異なります。自動生成と手動生成を同じEntityで重ねないことが重要です。
解決方法19:Generated Sourceを確認する
Code Generation Tool、Swift Macro、Build Pluginなどが同じType名やMember名を生成していないか確認します。
自分で書いていないDeclarationが原因の場合は、Build LogやGenerated Sourcesを確認してください。
解決方法20:同じGenerated Fileを2回Compileしていないか確認する
Generated Fileが複数のBuild PhaseやSource Directoryから重複して取り込まれると、同じDeclarationが2回Compileされる構成になる場合があります。
XcodeのTarget設定で:
Build Phases → Compile Sources
を確認します。
解決方法21:Compile Sourcesの重複や不要Fileを確認する
同じSource FileのCopyや古いFileがCompile Sourcesへ残っていないか確認します。
ただし、通常Xcodeが同一File Referenceを単純に二重登録する問題よりも、内容が同じ別Fileが含まれているケースの方が多いため、File Nameだけでなく中身も確認してください。
解決方法22:Target Membershipを確認する
同じTypeを持つFileを複数Targetで使うこと自体は問題にならない場合がありますが、同じTarget・Module内に重複Declarationが入るとErrorになります。
File Inspectorで、どのTargetに含まれているか確認してください。
解決方法23:同じModule内のGlobal Declarationを検索する
Global Function:
func logMessage( _ message: String ) { }
が複数Fileに存在していないかProject Searchで確認します。
解決方法24:Nested TypeのNameを変更する
struct Response { struct Item { }
struct Metadata {
}
}
同じContainer内のNested Type名を一意にします。
解決方法25:Merge Conflict後の重複Codeを確認する
Git MergeやCherry-pick後に、同じMethodが離れた場所へ2回残っていないか確認してください。
例えば:
func configureUI() { ... }
をProject Searchして、同じType内に複数ないか確認します。
解決方法26:OverloadのSignatureを意図的に区別する
例えばStringとURLで処理を分けたいなら:
func load( value: String ) { }
func load(
value: URL
) {
}
のようにConcrete Typeを変えます。
解決方法27:Argument LabelでAPIの意味を分ける
func load( id: Int ) { }
func load(
index: Int
) {
}
Call Siteで意味を明確に区別できるため、単なるDuplicate Declarationより読みやすいAPIになります。
解決方法28:同名PropertyをComputed PropertyとStored Propertyで重複させない
問題:
struct User { var name = "Alice"
var name: String {
"Bob"
}
}
Stored PropertyとComputed Propertyでも同じNameを共有できません。
例えば:
struct User { var name = "Alice"
var displayName: String {
name.uppercased()
}
}
のように役割ごとにNameを分けます。
解決方法29:同名MethodとPropertyの衝突を確認する
同じMember Nameを異なる種類のDeclarationで使うと衝突する場合があります。
APIとして分かりやすい別名へ変更してください。
解決方法30:XcodeのProject SearchでDeclarationを絞り込む
例えばErrorが:
Invalid redeclaration of 'reset'
なら:
func reset
や:
var reset
をProject Searchすると原因を見つけやすくなります。
SwiftUIで「Invalid redeclaration」が出る場合
SwiftUIではViewをFile単位で増やすことが多いため、同じType Nameを作ってしまうケースがあります。
特に確認するもの:
- ContentViewが複数ないか
- Custom ViewをCopyした後にStruct Nameを変更したか
- Preview用のTest Viewと本番Viewが同名でないか
- Extensionで同じComputed Propertyを追加していないか
- 同じViewModelを複数Fileで定義していないか
ClassやStructで発生する場合
例えば:
final class SettingsViewModel { var title = "" var title = "" }
なら、同名Propertyの片方を削除するかRenameします。
別Fileにも同じSettingsViewModelがないかProject全体で確認してください。
Functionで発生する場合
問題:
func calculate( value: Int ) -> Int { value * 2 }
func calculate(
value: Int
) -> Int {
value * 3
}
処理内容が異なってもSignatureが同じなので区別できません。
例えば:
func doubled( value: Int ) -> Int { value * 2 }
func tripled(
value: Int
) -> Int {
value * 3
}
のようにNameを変えます。
Extensionで発生する場合
Type本体とExtensionを両方検索します。
struct User { func formattedName() -> String { "User" } }
extension User {
func formattedName() -> String {
"User"
}
}
同じMemberは一方だけにします。
Core Dataで発生する場合
NSManagedObject Subclassを手動生成した後にEntityのCodegenがClass Definitionのままだと、同じClassが自動生成され、手書きClassと衝突する場合があります。
確認する流れ:
- .xcdatamodeldを開く
- 対象Entityを選択する
- Data Model Inspectorを開く
- ClassとModuleを確認する
- Codegen設定を確認する
- 自動生成か手動管理かを統一する
「Project内に1つしかないはず」なのに出る場合
次を確認してください。
- 同じDeclarationを持つCopy File
- Target Membership
- Extension
- Generated Source
- Core Data Codegen
- Swift MacroやBuild Pluginの生成物
- 別Folderにある古いSource
- Merge後に残ったDuplicate Code
- Compile Sourcesへ含まれているFile
Clean Build Folderで直るか
通常、Source Code上に本当に重複Declarationがある場合はClean Build Folderでは直りません。
補助的に:
Product → Clean Build Folder
を試すことはできますが、同じTypeやMemberが2つ定義されていればCode修正が必要です。
DerivedData削除は必要か
IndexやGenerated Artifactの古い状態が疑われる場合には、補助的なTroubleshootingとしてDerivedDataを削除することがあります。
rm -rf ~/Library/Developer/Xcode/DerivedData/*
ただし、これはProject内のDuplicate Declarationを削除する操作ではありません。
注意:まずProject Searchで同名Declaration、Target Membership、Generated Codeを確認してください。Cache削除は最後の補助策です。
やってはいけない対処
Errorを消すためだけに、意味のないSuffixを付けて片方を残す方法は避けてください。
例えば:
func save2() { }
のように適当にRenameすると、APIの役割が分かりにくくなります。
本当に同じ機能ならDuplicateを削除し、別の機能なら役割を表すNameへ変更してください。
また、重複しているFileをFinderから削除する前に、そのFileが必要なSourceではないか、Version Controlで復元可能かも確認してください。
最短で確認するチェックリスト
- Errorに表示された名前をProject全体で検索する
- 同じFile内に重複Declarationがないか確認する
- 別Fileに同名Class・Struct・Enumがないか確認する
- FunctionならSignature全体を比較する
- Extensionで同じMemberを定義していないか確認する
- Copy FileやBackup Fileを確認する
- Target Membershipを確認する
- Build PhasesのCompile Sourcesを確認する
- SwiftUIのContentViewなど同名Viewを確認する
- Enum Caseの重複を確認する
- TypealiasとType Nameの衝突を確認する
- IBOutlet・IBActionの重複を確認する
- Generated Sourceを確認する
- Core DataのCodegenを確認する
- Merge後のDuplicate Codeを確認する
まとめ
Swiftの「Invalid redeclaration」は、Compilerから見て同じ名前・同じSignatureとして扱われるDeclarationが重複している場合に発生します。
代表的な原因は、同名Variable・Property・Function・Class・Struct・Enumの重複、Extension内のDuplicate Member、Copy File、SwiftUIの同名View、Generated Code、Core Data Codegenなどです。
最初にError Messageへ表示されたNameをXcodeのProject Searchで検索し、同じDeclarationがどこに存在するか確認してください。
本当に重複しているだけなら不要なDeclarationを削除し、別の役割を持つものなら意味が分かるNameへ変更します。
Functionを同名で使いたい場合は、Parameter TypeやArgument Labelなど、Compilerが明確に区別できるSignatureへ変更してOverloadとして設計します。
Project内に重複が見つからない場合は、Target Membership、Extension、Generated Sources、Core DataのCodegen、Build Phasesも確認してください。
Clean Build FolderやDerivedData削除は補助的な対処にすぎず、Source Code上のDuplicate Declarationそのものは修正できません。
