このコードを呼び出しています:
if ([refreshViewControllerDelegate conformsToProtocol:@protocol(ReloadViewControllerDelegate)])
しかしrefreshViewControllerDelegate
、これは次のとおりです。
id refreshViewControllerDelegate;
conformsToProtocol
オブジェクトがプロトコルに準拠していることを宣言しているかどうかを確認しますが、あなたのものはそうではありません。プロトコルへの準拠を指定する場合は、次のことを行う必要があります。
id<ReloadViewControllerDelegate> refreshViewControllerDelegate;
編集
OK、performSelectorOnMainThread
問題について... そのメソッドは NSThread のカテゴリで提供されており、NSObject プロトコルでは宣言されていません。したがって、それを呼び出したい場合は、型をプロトコルに準拠した NSObject として宣言する必要があります。
NSObject<ReloadViewControllerDelegate> refreshViewControllerDelegate;
編集
OK、これはプロトコルの使用に関する単純な質問ではなく、完全なチュートリアルのようです。SOはそのような場所ではないので、簡単に説明します...
プロトコルはインターフェイス宣言です。
@protocol ReloadChatViewControllerDelegate <NSObject>
- (void)refreshViewController:(NSString *)result;
@end
それは、名前の付いた新しいプロトコルが町にあり、ReloadChatViewControllerDelegate
それもプロトコルに準拠していることを示していNSObject
ます。新しいプロトコルを採用するすべてのクラスは、 の実装を提供する必要がありますrefreshViewController
。セクションを入れることで、プロトコルメソッドをオプションにすることができます@optional
。
@protocol ReloadChatViewControllerDelegate <NSObject>
- (void)refreshViewController:(NSString *)result;
@optional
- (void)optRefresh;
@end
さて、プロトコルの採用については後回しにしましょう。汎用コードを書いていて、与えられたオブジェクトがプロトコルに準拠しているかどうかを知りたいだけで、準拠している場合はメソッドを呼び出すとします。何かのようなもの...
@interface Bar : NSObject
@property (nonatomic, weak) NSObject<ReloadChatViewControllerDelegate> *refreshViewControllerDelegate;
- (void)blarg;
@end
現在、Bar クラスはデリゲート プロパティを提供しているため、何らかの作業を行うのに役立つオブジェクトを与えることができます。ただし、そのデリゲート オブジェクトは、少なくとも であり、プロトコルNSObject
に準拠している必要があります。ReloadChatViewControllerDelegate
現在、ObjC (および C) は非常に寛容であるため、オブジェクトを強制的に任意の型にすることができますが、クラッシュするのは当然のことです。blarg
が呼び出されると、デリゲートは何らかの作業を行うように通知されます。
デリゲートのプロパティ タイプは、指定されたプロトコルに準拠していると既に述べているため、準拠を確認する必要はありません。デリゲート メソッドを呼び出すだけです。オブジェクトがオプションのプロトコル メソッドを実装しているかどうかを確認する必要があることに注意してください。
@implementation Bar
@synthesize refreshViewControllerDelegate = _refreshViewControllerDelegate;
- (void)blarg {
// Do something, then invoke the delegate
[self.refreshViewControllerDelegate
performSelectorOnMainThread:@selector(refreshViewController:)
withObject:@"YES"
waitUntilDone:NO];
if ([self.refreshViewControllerDelegate respondsToSelector:@selector(optRefresh)]) {
[self.refreshViewControllerDelegate optRefresh];
}
}
@end
ただし、一般的であり、任意のオブジェクトをデリゲートとして受け入れたい場合 (デリゲートが特定のプロトコルに準拠することをオプションにしたい場合もあります)、プレーンを受け入れてid
から、それが準拠しているかどうかを確認できます。その場合、デリゲートを単なる id (または他の型) として宣言できます。
@property (nonatomic, weak) id refreshViewControllerDelegate;
ここで、コード内で適合性をチェックする必要があります。
- (void)blarg {
// Do something, then invoke the delegate
if ([self.refreshViewControllerDelegate
conformsToProtocol:@protocol(ReloadChatViewControllerDelegate)]) {
[self.refreshViewControllerDelegate
performSelectorOnMainThread:@selector(refreshViewController:)
withObject:@"YES" waitUntilDone:NO];
if ([self.refreshViewControllerDelegate
respondsToSelector:@selector(optRefresh)]) {
[self.refreshViewControllerDelegate optRefresh];
}
}
}
OK、これでプロトコルが定義され、プロトコルでメソッドを呼び出すコードができました。2 つの注意事項。
まず、デリゲートをオブジェクトに設定する必要があります。 nil
はどのメソッドにも応答するfalse
ため、もちろん準拠せず、メッセージが送信されても何もしません。
次に、デリゲートがプロトコルへの準拠を宣言していることを確認する必要があります。メソッドを実装するだけでは適合しません。クラスがプロトコルに準拠していることを明示的に指定していない場合、conformsToProtocol
プロトコルのメソッドを実装していても false を返します。
そこで、プロトコルに準拠してデリゲートとして機能するクラスを指定しましょう。
@interface Foo : NSObject<ReloadChatViewControllerDelegate>
- (void)refreshViewController:(NSString *)result;
@end
@implementation Foo
- (void)refreshViewController:(NSString *)result {
NSLog(@"Look, ma, I'm refreshed with %@", result);
}
@end
プロトコルに準拠し、必須メソッドの実装を提供し、オプションのメソッドを省略します。
さて、このコードを実行すると、素晴らしいコードが見事に表示されるはずです。
Foo *foo = [[Foo alloc] init];
Bar *bar = [[Bar alloc] init];
bar.refreshViewControllerDelegate = foo;
[bar blarg];