11

このプロトコル定義を考えると:

@protocol MyProtocol <NSObject>
@property (nonatomic, strong) NSString *someProperty;
@end

Xcodeがこのステートメントのオートコンプリートを喜んで提供するのはなぜですか。

id<MyProtocol> thing = [ThingManager currentThing];
[thing someProperty]; // Xcode offered autocompletion here

しかし、ドット表記を使用して同じプロパティにアクセスしようとすると、オートコンプリートは提供されません。

id<MyProtocol> thing = [ThingManager currentThing];
thing.someProperty; // Xcode claimed there were 
                    // "No completions" available
                    // after the period
4

2 に答える 2

6

は基本タイプであるためid、XcodeとCLANGは、ドット構文が通常のオブジェクトの関連するセッターまたはゲッターへのメソッド呼び出しの単なる構文糖衣であるため、ドット構文アクセスを提供することに不安を感じていますが、idにはメソッドメンバーが定義されていません。C側から見ると、idは構造体ポインターのtypedefであり、コンパイラーはそのメンバーを認識できません。つまり、メンバーにアクセスできません(dot-accessの前にidを逆参照する必要があるという事実を気にしないでください)。意味的に意味があります)。

物事のObjective-C側に戻ると、プロトコルは実際にはそれらを実装すると主張するクラスにメソッドやプロパティを追加しません。むしろ、特定のプロトコルに準拠するオブジェクトが一連のを実装する他のクラスへの指定子として機能します。メソッド。メソッド構文が完了すると、Xcodeは、指定された.mファイルにインポートされたすべてのファイルの指定されたすべてのメソッドをプールします。これは、タイプidのオブジェクトが任意のメッセージを受信できるためです*。

*もちろん、メッセージを受信することはできますが、実装されていない場合はクラッシュします。

于 2013-01-26T06:08:03.170 に答える
2

これは一種の接線の答えであり、思考実験です。

idただし、その前に、次のようにスキップすることでプロパティをオートコンプリートできることに注意してください。

NSObject<MyProtocol> *thing;
thing.▮

NSObjectしかし、メソッドのリスト全体が完成度を上げたくないと仮定すると、次のようなことができます。

EmptyClass<MyProtocol> *thing = [ThingManager currentThing];

// completion list will be (close) to only the protocol props
thing.▮

EmptyClass同様の「OK、約束はありません!」役割idはありますが、オートコンプリートはそれが好きです。ここにありEmptyClassます:

NS_ROOT_CLASS
@interface EmptyClass

@end

@implementation EmptyClass

+ (void)initialize {} // required

@end

念のために言っておきますが、のオブジェクトthingは実際には根付いていないEmptyClassできない)ので、これは非常に偽物です。しかし、それは

  • thing実際に何ができるかを大いに約束していません。
  • オブジェクトをインスタンス化しません(できません! )。EmptyClass

では、なぜですか?本当に一生懸命頑張ると、次のような問題が発生する可能性があります

EmptyClass *nooooo = [[NSClassFromString(@"EmptyClass") alloc] init];

これはすぐに例外になります。しかし、避けるべきトリッキーなバグではありません。

落とし穴は私を驚かせませんが、私は今それを知りません。よろしければコメントを残してください。

于 2014-05-02T17:49:46.387 に答える