0

私は次のようにディスパッチされた通知にアクセスしています:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleUnpresent:) name:UNPRESENT_VIEW object:nil];

...

-(void)handleUnpresent:(NSNotification *)note;
{
    NSLog(@"%@", note.object.footer);
    //property 'footer' not found on object of type 'id'
}

着信note.objectオブジェクトには「フッター」があるものとないものがあります。ただし、これを機能させるためだけに呼び出されるプロパティのみを持つクラスを作成するという問題に直面したくありませんfooter((NSObject *)note.object).footer)私はいくつかの言語で動作するものを試しましたが、どうやらobj-cではありません。私に何ができる?

4

3 に答える 3

2

をチェックすることisKindOfClassは確かにより強力なオプションです。ただし、必要なプロパティを返す無関係のクラスが複数ある場合は、別の方法がありますrespondsToSelector。オブジェクトにメソッドがあるかどうかを尋ねるだけfooterで、安全に呼び出すことができます。

-(void)handleUnpresent:(NSNotification *)note;
{
    id noteObject = [note object];
    if ([note respondsToSelector:@selector(footer)])
    {
        NSLog(@"Footer = %@", [noteObject footer]);
    }
}

そのrespondsToSelector方法は、適切な場所で強力で便利ですが、それに夢中にならないでください。また、リターンタイプについては何も教えてくれないので、footer期待していたクラスではないかもしれません。

との構文はnoteObject.footer[noteObject footer]同等のものとして扱いやすいです。ただし、のクラスnoteObjectが不明な場合、コンパイラは後者を受け入れますが、前者は受け入れません。noteObject通常はに応答しない定義済みのクラスがある場合footer、警告が表示されますが、コンパイルして実行されます。このような場合、必要なときにメソッドが実際に存在すること、したがって実行時にメソッド呼び出しがクラッシュしないことを保証するのはユーザーの責任です。

于 2012-04-15T05:11:18.110 に答える
1

NSObject、という名前のプロパティがないfooterため、コンパイラが文句を言っています。IDをにキャストして戻すことNSObjectは役に立ちません。オブジェクトが常に作成したカスタムオブジェクトになることがわかっている場合は、それにキャストバックしてフッターを呼び出すと、コンパイラは文句を言いません。実際に確認するのが一番です。以下の例を参照してください(例として、footerプロパティを持つクラスに名前を付けたViewWithFooterので、適切に名前を変更します)。

- (void)handleUnpresent:(NSNotification*)note
{
  ViewWithFooter view = (ViewWithFooter*)[note object];
  NSParameterAssert([view isKindOfClass:[ViewWithFooter class]]);
  UIView* footer = [view footer];
  // Do something with the footer...
  NSLog(@"Footer: %@", footer);
}

すべてがプロパティを提示する無関係なクラスが多数ある場合(つまり、同じクラス階層にない場合)footer、必要なfooterプロパティを使用してプロトコルを作成し、上記のコード例のプロトコルにオブジェクトをキャストするのが最適です。それをアサートすると、-footerセレクターに応答します。

プロトコルを使用した例を次に示します。

@protocol ViewWithFooter <NSObject>

- (UIView*)footer; // this could also be a readonly property, or whatever

@end

- (void)handleUnpresent:(NSNotification*)note
{
  id<ViewWithFooter> view = (id<ViewWithFooter>)[note object];
  NSParameterAssert([view respondsToSelector:@selector(footer)]);
  UIView* footer = [view footer];
  // Do something with the footer...
  NSLog(@"Footer: %@", footer);
}
于 2012-04-15T04:30:25.203 に答える
1

object渡された通知がいくつかのクラスの1つであり、オブジェクトを特定のクラスにキャストしたくない場合は、オブジェクトのメソッドを呼び出すために使用できますperformSelector:footerこの呼び出しをaでラップするとrespondsToSelector:、オブジェクトにメソッドがないことが判明した場合に例外を回避できますfooter

-(void)handleUnpresent:(NSNotification *)note;
{
    if ([[note object] respondsToSelector:@selector(footer)]) {
        NSString *footer = [[note object] performSelector:@selector(footer)];

        NSLog(@"%@", footer);
    }
}

を使用performSelectorすると、コンパイラが「'id'型のオブジェクトに'フッター'が見つかりません」という文句を言うのをやめます。

于 2012-04-15T05:36:31.440 に答える