PC パソコン

Xcode『Could not instantiate class named』の解決方法

XcodeでStoryboardやXIBを読み込んだとき、実行時に「Could not instantiate class named …」と表示されてアプリがクラッシュすることがあります。このエラーは、Interface Builder上に保存されているカスタムクラス名を、実行時にUIKitが見つけられないときに発生します。

エラーの意味

Could not instantiate class named MyViewController

StoryboardやXIBには、画面やViewに割り当てたCustom Classの情報が保存されています。実行時にそのクラスを生成しようとしても、アプリ内に該当クラスが存在しない、Moduleが違う、ターゲットに含まれていないなどの理由でクラスを解決できないと、このエラーが発生します。

代表的な発生状況

  • Swiftクラスの名前を変更したが、Storyboard側のCustom Classが古いまま残っている
  • クラスファイルを削除したのにStoryboardやXIBに参照が残っている
  • Identity InspectorのModuleが別ターゲットや古いプロジェクト名になっている
  • SwiftファイルのTarget Membershipが外れている
  • 別Frameworkや別Moduleにクラスを移動した
  • Storyboardをコピーした際に元プロジェクトのModule情報が残った
  • Objective-C Runtimeから参照できない形でクラスを定義している

まず確認する手順

1. エラーに表示されたクラス名を確認する

コンソールに表示されたクラス名を確認します。たとえば次のように表示されている場合は、StoryboardまたはXIB内にMyViewControllerというクラス指定が残っています。

Could not instantiate class named MyViewController

2. StoryboardまたはXIBのCustom Classを確認する

問題のView ControllerやViewを選択し、右側のIdentity Inspectorを開きます。Custom ClassのClass欄とModule欄が、現在のSwiftまたはObjective-Cクラスと一致しているか確認します。

3. クラスがターゲットに含まれているか確認する

該当するSwiftファイルを選択し、File InspectorのTarget Membershipで、実行するアプリターゲットにチェックが入っているか確認します。

解決方法1:StoryboardのCustom Classを正しいクラス名に直す

クラス名を変更した場合は、Storyboard側も同じ名前に更新します。

class MainViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Swift側がMainViewControllerなら、Identity InspectorのClassもMainViewControllerにします。

解決方法2:Moduleを正しく設定する

Class名が正しくてもModuleが別プロジェクトや別ターゲットを指していると、実行時にクラスを見つけられません。Identity InspectorのModuleを現在のアプリModuleに変更します。

通常は「Inherit Module From Target」にチェックを入れると、現在のターゲットに合わせて解決されやすくなります。

プロジェクト名を変更した後や、Storyboardを別プロジェクトからコピーした後は、古いModule名が残っていないか特に確認してください。

解決方法3:Target Membershipを有効にする

クラスファイルがプロジェクト内に存在していても、ビルド対象ターゲットに含まれていなければアプリには組み込まれません。

  1. Project Navigatorで該当Swiftファイルを選択する
  2. File Inspectorを開く
  3. Target Membershipで実行対象のアプリターゲットにチェックを入れる
  4. 再ビルドする

解決方法4:削除済みクラスの参照をStoryboard/XIBから消す

以前使っていたクラスを削除した場合、Interface Builder側に古いCustom Class指定だけが残ることがあります。不要なViewやView ControllerならCustom Classを空欄に戻すか、正しいクラスへ差し替えます。

解決方法5:StoryboardをSource Codeで検索する

どの画面に古いクラス名が残っているかわからない場合は、StoryboardをSource Codeとして開き、エラーに出ているクラス名を検索します。

customClass="MyViewController"
customModule="OldProjectName"

古いcustomClassやcustomModuleが見つかったら、Interface Builder上で該当オブジェクトを修正するのが安全です。

解決方法6:別FrameworkやModuleに移した場合を確認する

カスタムViewやView ControllerをFrameworkへ移した場合は、StoryboardのModuleもそのFrameworkに合わせる必要があります。また、そのFrameworkが対象アプリにリンク・埋め込みされていることも確認してください。

解決方法7:Objective-C Runtimeから見えるクラス名を確認する

Storyboard/XIBは実行時にクラスを名前で解決します。SwiftクラスをObjective-C Runtime経由で参照する構成では、クラス名やModule境界の変更が影響する場合があります。

必要に応じて、クラスをObjective-C Runtimeから明示的に参照できるようにします。

@objc(MyCustomView)
class MyCustomView: UIView {
}

@objcをむやみに追加する必要はありません。まずはStoryboardのClass、Module、Target Membershipの不一致を確認するのが優先です。

解決方法8:Clean Build FolderとDerivedDataを確認する

設定を直しても古いビルド情報が残っている場合は、Clean Build Folderを実行してから再ビルドします。それでも改善しない場合はDerivedDataを削除します。

rm -rf ~/Library/Developer/Xcode/DerivedData/*

削除後にXcodeを開き直し、再ビルドしてください。

コマンドでクラス名の残存を確認する

プロジェクト内に古いクラス名が残っているか確認したい場合は、プロジェクトディレクトリで次のように検索できます。

grep -R "MyViewController" .

Storyboard、XIB、ソースコード、設定ファイルなどに古い参照が残っていないか確認できます。

注意点

  • Class名だけでなくModule名も確認してください。
  • Swiftファイルが存在するだけでは不十分で、Target Membershipに含まれている必要があります。
  • StoryboardやXIBを他プロジェクトから流用した場合は、元プロジェクトのModule名が残りやすいです。
  • 同名クラスが複数Moduleに存在する場合は、どのModuleを参照しているか確認してください。
  • DerivedData削除は最後の確認手段であり、設定不一致そのものは直りません。

まとめ

「Could not instantiate class named」は、StoryboardやXIBが指定しているカスタムクラスを実行時に見つけられないときに発生します。まずIdentity InspectorでClassとModuleを確認し、次にTarget Membership、削除済みクラスの参照、別Moduleへの移動を確認してください。設定を修正しても改善しない場合はClean Build FolderやDerivedData削除を行い、古いビルド情報を除去すると解決につながります。