18

ここのガイドに従って、カスタム デリゲートを作成します。正常に動作しますが、xcode で次の警告が表示されます

DetailViewController.m:23:1: 自動合成されたプロパティ 'delegate' は、既存のインスタンス変数 'delegate' ではなく、合成されたインスタンス変数 '_delegate' を使用します

誰でも警告を取り除く方法をアドバイスできますか

4

2 に答える 2

39

この状況を処理する最も慣用的な方法は、単純にdelegateivar 宣言を削除することです。ivar を使用していた場合は、代わりdelegateに暗黙の ivar を使用する必要があります_delegate

なぜこれが機能するのですか?

Xcode 4.4 (LLVM Compiler 4.0)の時点で、ディレクティブがそのプロパティに対して明示的に使用されていない場合@synthesize、インスタンス変数とアクセサ メソッドはそのプロパティに対して自動的に合成されます。カプセル化状態に関するAppleのドキュメントとして

デフォルトでは、[...] アクセサー メソッドはコンパイラによって自動的に合成されるため、クラス インターフェイスで @property を使用してプロパティを宣言する以外に何もする必要はありません。

プロパティ (自動的に合成されたプロパティ アクセサー メソッドによって取得および設定される) に使用される ivar には名前が付けられます_<propertyName>(つまり、ivar の名前は、プロパティの名前の前にアンダースコアが付きます)。

この場合、プロパティ名はdelegateであるため、使用される ivar は です_delegate。これはあなたのコードですでに起こっています。andを呼び出す-delegate-setDelegate:、この ivar_delegateが取得および設定されます。

ただし、独自の ivar も宣言していますdelegate。もちろん、明示的に宣言した ivar ( delegate) は、インスタンス メソッドによって取得および設定されません。-delegateこれ-setDelegate:は、自動的に合成された ivar ( _delegate) が取得および設定されているためです。ただし、(ほとんどの場合、そうでない場合、コードはあいまいです) あなたの意図は、ivardelegateがプロパティのアクセサーが取得および設定するものになることでした。幸いなことに、コンパイラはあなたが行ったことに気付くほど賢いので、次の警告が表示されます。

警告: 自動合成されたプロパティ ' ' は、既存のインスタンス変数 ' ' ではなく、delegate合成されたインスタンス変数 ' ' を使用します[ ]_delegatedelegate-Wobjc-autosynthesis-property-ivar-name-match

プロパティが、明示的に宣言した ivar ではなくdelegate、自動的に合成された ivar を使用することを示しています。_delegatedelegate

したがって、単純にdelegateivar を削除すると、コンパイラはこの警告の発行を停止します。delegateivar を (プロパティ経由ではなく) 直接使用していた場合は、_delegate代わりに使用を開始してください。


このオプションのマイナー バリエーションは、プロパティ_delegateの自動合成が作成するのと同じ ivar ( )を明示的に宣言することです。delegate置き換えることでこれを行うことができます

@interface TheClass : TheSuperclass
{
    //...
    id<TheDelegateProtocol> delegate
    //...
}
@end

@interface TheClass : TheSuperclass
{
    //...
    id<TheDelegateProtocol> _delegate
    //...
}
@end

これが機能するのは、プロパティの自動合成では常に、プロパティの名前の前にアンダースコアが付けられた ivar が使用されるためです。そのような ivar が存在しない場合は、ivar が生成されます。存在する場合は、それが使用されます。


代わりに、プロパティのアクセサーを設定して ivar を取得したい場合は、クラスにディレクティブをdelegate追加して、コンパイラにこれを行うように指示できます。@synthesize@implementation

@implementation TheClass
//...
@synthesize delegate = delegate;
//...
@end

この行は、プロパティ(割り当ての左側) のアクセサーで@synthesize delegate = delegate;ivar delegate(割り当ての右側)を使用するようコンパイラーに指示します。delegate

@synthesize割り当ての右側を省略して、単に書くこともできます

@implementation TheClass
//...
@synthesize delegate;
//...
@end

これが機能@synthesizeするのは、アクセサー ( など) によって取得および設定される ivar を明示的に指定していないマニュアルを@synthesize delegate;持つプロパティは、アンダースコアをプレフィックスとして付けずに、プロパティと同じ名前の ivar を使用するためです。これは下位互換性に関係しています。

于 2013-01-06T17:28:53.323 に答える
2

別の方法があり、これは私のために働いた:

@property (nonatomic, unsafe_unretained) id <MyDelegate> delegate;

その後、これをエラーなしで実装に追加できます。

@synthesize delegate;

また、これは ARC 準拠です。

于 2013-02-21T14:51:10.827 に答える