1. ホーム
  2. APP開発
  3. IOS

iOS classic error Undefined symbols for architecture XXX:

2022-01-22 09:23:04

を宣言して開始します。

実機でコンパイルしたため、エラーを報告するアーキテクチャ(CPUの命令セット)はarm64です。

  • 64ビットエミュレータ(iPhoneシミュレータ5s以上)を使用してプロジェクトをコンパイルまたは実行すると、以下のエラーが報告されます。

アーキテクチャ x86_64 で未定義のシンボルがあります。

  • 32ビットエミュレータ(iPhoneシミュレータバージョン5以下)でプロジェクトをコンパイルまたは実行すると、以下のエラーが表示されます。

アーキテクチャ i386 で未定義のシンボルがあります。

Undefined symbols for architecture XXX: このようなエラーは開発においてよくある問題で、サードパーティ製の静的ライブラリを含むプロジェクトでは避けられないものです。エラーの原因を説明し、解決策の理解を深めてもらうため。著者は、意図的に問題を再現して解決策を検証しています。
まず最初に、記録として、私のプロジェクトは(cocoapods経由ではなく)AUのlibMobClickLibrary.aという統計SDKを参照しています。それはプロジェクトのthird_partyディレクトリに、以下のように格納されています。

静的ライブラリディレクトリ

原因の1つ:libライブラリがリンクされておらず、エラーが報告される

libはライブラリという意味で、libライブラリは接尾辞が.aの静的ライブラリのことです。
(1) 一般 -> Linked Frameworks and Libraries の libMobClickLibrary.a を削除します。削除前と削除後の比較はそれぞれ下図のとおりです。

削除前

この時点で、静的ライブラリがリンクされます

削除後

この時点でスタティック・ライブラリはリンクされなくなります。

(2) 再度、実際にプロジェクトをコンパイルしてみると、次のような2つの古典的なエラー "OBJC_CLASS$_MobClick", referenced from: and linker command failed with exit code 1 (use -v to see invocation), click on first errorが表示されるでしょう。

Snip20161219_11.png

(3) 次に、アーキテクチャ arm64 の未定義シンボルを参照してください。

Snip20161219_4.png

しかし、libMobClickLibrary.aライブラリがリンクされておらず、他のライブラリでないことをどうやって確認するのでしょうか?また、この "_OBJC_CLASS_$_MobClick", referenced from: に依存しています。ここで _OBJC_CLASS_$_MobClick の MobClick は libMobClickLibrary.a の中で参照したファイルなんです。というのも、以下のように#import "MobClick.h"を介してAliyunSalesCustomerListTableViewManager.m内のMobClick.hを本当に参照してしまったのです。

Snip20161219_12.png

もちろん、libMobClickLibrary.aライブラリの他のファイルを参照する場合は、OBJC_CLASS$_にMobClickが続かないので、誰もがよく理解しているはずです。

背後のクラス名がサードパーティのライブラリ名と似ていないため、例えばライブラリ名はlibAAA.aだが、エラーを報告するクラス名はBBBということもある。この時、BBBの後ろのクラス名ではどのライブラリに属しているのかが正確に分からず、どのライブラリにリンクすればいいのかが分からない。この場合、参照された from: プロンプトの後のファイル名から、BBBがどの静的ライブラリに属しているかを判断することができますが、自作のクラスファイルが多くのサードパーティライブラリをインポートすることは考えにくいので、この場合はこの方法で判断した方がよいでしょう。

まとめますと まとめると、サードパーティのスタティック・ライブラリがプロジェクトで使われていても、libのスタティック・ライブラリやフレームワークのスタティック・ライブラリがリンクされていないと、Undefined symbols for architecture XXXなどのエラーに遭遇することがわかっています。
<スパン 原因 プロジェクトをコンパイルする際、スタティック・ライブラリはプロジェクトにリンクされていないので、スタティック・ライブラリはコンパイルに参加しません。プロジェクトのいくつかのファイル(.mファイル)はスタティック・ライブラリを参照している(または依存している)ので、当然エラーが報告され、報告されたエラーはクラシックなUndefined symbols for architecture XXXという種類のエラーとなります。
<スパン 解決策 次回このような問題が発生した場合は、指定した静的ライブラリをLinked Frameworks and Librariesに追加するだけです

プロジェクトを復元する

先ほど libMobClickLibrary.a ファイルを削除したので、プロジェクトを完全にコンパイルして実行する状態に戻すために、以下のように libMobClickLibrary.a ライブラリを Linked Frameworks and Libraries に追加する必要があります。

このライブラリは、システム提供のライブラリではなく、サードパーティーのライブラリであるため、独自のディレクトリに追加する必要があります。

ステップ1:「追加」をクリック

ステップ2:「その他を追加」をクリック

ステップ3:静的ライブラリを選択し、開くをクリックします。

この時点で、欠落していたスタティック・ライブラリはプロジェクトにリンクされたので、再度プロジェクトをコンパイルしても、このエラーは発生しません。もちろん、それでも同様のエラーが発生する場合は、同じようにプロジェクトにリンクする必要のある静的ライブラリが他にもあるはずです。

原因2:.frameworkのスタティック・ライブラリがリンクされておらず、エラーが発生する。

上記は、あるプロジェクトで、リンクされた lib ライブラリがないためにエラーが報告されている状況を示しています。ですから、推測するのは難しくありません。リンクされた.framework形式のスタティック・ライブラリが見つからない場合も、同じエラーが発生します。
.a形式のスタティック・ライブラリではなく、Linked Frameworks and Librariesでリンクされていない.framework形式のスタティック・ライブラリをサードパーティから参照した場合も、同じエラーが報告されます。例えば、Linked Frameworks and LibrariesでPushCenterSDK.frameworkというスタティックライブラリを削除すると(このスタティックライブラリは木目調で、cocoapodsでは管理していない)、次のようになります。
(1) Linked Frameworks and LibrariesからPushCenterSDK.frameworkを削除する。

.frameworkのスタティック・ライブラリを削除します。

(2) シミュレータでプロジェクトをコンパイルすると、以下の3つのエラーが発生します。

リンクされた静的ライブラリがないため、コンパイルエラーになる

(3) 最初のエラーをクリックすると、次のようにエラーの詳細が表示されます。

エラーの詳細

見つかりました。.framework形式のスタティック・ライブラリがない場合も同じエラーが報告されます。したがって、リンクされた.aスタティック・ライブラリがない場合でも.frameworkスタティック・ライブラリがない場合でも、「フレームワークとライブラリのリンク」で正しくリンクされていなければ、同じエラー、すなわち「Undefined symbols for architecture XXX: 」が報告されることになります。

ここで注目すべきは、YunFuPushCenter.m ファイルが PushCenterSDK.framework の 2 つのファイルを参照しているため(下図参照)、3 つのエラーが報告され、さらに 1 つのエラーが報告されていますが、これは次のように理解するのがよいでしょう。

フレームワークから2つのファイルが参照されています

理由3:externが存在しないグローバル変数を参照し、エラーを報告するため

開発では、グローバル変数を使用することが多く、例えば、delegate.m ファイルでは int 型のグローバル変数 globalVar を定義し、ViewController.m ファイルでは extern int globalVar; で、このグローバル変数の A.m ファイルを参照することがあります。これは問題ない.しかし,誤って extern int globalVar を extern int globalVariate と書き,この globalVariate 変数を ViewController.m ファイルで使用すると(コードは以下のようになります),以下のようになります.

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

int globalVar; // life a global variable
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    return YES;
}

Copy the code

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

extern int globalVariate; // reference a global variable that does not exist
- (void)viewDidLoad {
    [super viewDidLoad];

    globalVariate = 10; // assign a value to a non-existent global variable
}

@end

Copy code

上記のコードをコンパイルしても、以下のように同じエラーが報告されます。

エラーをクリックすると、以下のように詳細が表示されます。

理由:extern int globalVariateはglobalVariateという変数を定義しておらず、globalVariateというグローバル変数を参照しているため。globalVariateを使用すると、システムはその変数が全く定義されていないことを発見し、このエラーを報告します。