5

マスターを作業ブランチにマージした後、行でコンパイラ エラーが発生しましたが、これは変更されませんでした。エラーは次のようになります

id test;
[test count];

「count」という名前のメソッドが複数見つかり、結果が一致しません。

コンパイラは「テスト」変数がどの具象型かを知らないため、最初は明確に見えます。しかし、なぜそれが以前に機能したのかわかりません。

  1. 新しいファイルを作成すると、それが NSArray のメソッドであると仮定して、この行が機能します。この場合、コンパイラがエラーを表示しないのはなぜですか?

  2. エラーメッセージを表示している間、count メソッドの受信者候補がいくつか表示されます。(NSArray, NSDictionary, NSSet) そのメッセージを受信できるすべてのクラスを検索し、複数ある場合はエラーを表示しますか?

  3. 「-Swift.h」ファイルをインポートするとエラーが発生することに気付きました。それはどのように依存しますか?

4

2 に答える 2

5

Objective-C は、レシーバーのタイプを知る必要はありません。実行時には、すべてのオブジェクトは単にidであり、すべてが動的にディスパッチされます。したがって、タイプに関係なく、任意のメッセージを任意のオブジェクトに送信できます。(実行時に、オブジェクトは、理解できないメッセージをどうするかを自由に決めることができます。最も一般的なのは、例外を発生させてクラッシュさせることですが、理解できない任意のメッセージを処理できるオブジェクトには多くの種類があります。 t メソッド呼び出しに直接マップします。)

ただし、これを複雑にする技術的な詳細がいくつかあります。

ABI (アプリケーション バイナリ インターフェイス) は、特定のプリミティブ型を返すためのさまざまなメカニズムを定義します。値が「ワードサイズの整数」である限り、それは問題ではありません (これには、NSIntegerおよびすべてのポインター、つまりすべてのオブジェクトの拡張が含まれます)。ただし、一部のプロセッサでは、浮動小数点数は整数とは異なるレジスタに返され、構造体 ( などCGRect) はサイズに応じてさまざまな方法で返される場合があります。必要なアセンブリ言語を記述するために、コンパイラはそれがどのような種類の戻り値になるかを知る必要があります。

ARC は、パラメーターの型 (具体的にはオブジェクトかプリミティブか) と、考慮しなければならないメモリ管理属性があるかどうかについて、コンパイラーがより多くのことを知ることを必要とする追加の問題を追加しました。

testコンパイラは、の型と属性を把握できる限り、「実際の」型が何であるかをあまり気にしません-count。そのため、値を処理するときは、id認識できるすべての既知のセレクター (つまり、インクルードされたヘッダーまたは現在の で定義されているすべてのセレクター) を調べます.m。全員が同意する限り、異なるクラスにそれらの多くが含まれていても問題ありません。しかし、セレクターがまったく見つからない場合、または一部のインターフェースが一致しない場合は、コード行をコンパイルできません。

lobstah が指摘しているように、Swift コードのどこかに、@objc呼び出されたメソッドcount()または名前が@objc付けられたプロパティを持ち、countそれが 以外のものを返す型を持っている可能性がありますInt(これは にマップされNSInteger、 の通常のシグネチャと一致します-count)。そのメソッドを修正するか、ObjC から非表示にする必要があります (たとえば、 を追加し@nonobjcます)。

または、はるかに良い: を取り除き、id実際の型を使用します。idこれは Cocoa では一般的に悪い考えであり、オブジェクトが応答することをコンパイラがチェックできず、クラッシュする可能性があるため、メソッドを呼び出している場合は特に悪い考えです。

于 2018-10-05T13:40:13.183 に答える