[解決済み] Objective-Cでデリゲートを作成するにはどうしたらいいですか?
質問
デリゲートがどのように機能するか知っていますし、どのように使用できるかも知っています。
しかし、どのように作成すればよいのでしょうか?
どのように解決するのですか?
Objective-Cのデリゲートは、オブジェクトに割り当てられた
delegate
プロパティを使用します。デリゲートメソッドを実装するクラスを定義し、そのクラスがデリゲートプロトコルを実装しているとマークします。
例えば
UIWebView
. もし、そのデリゲートの
webViewDidStartLoad:
というメソッドがあれば、このようなクラスを作成することができます。
@interface MyClass<UIWebViewDelegate>
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
そして、MyClass のインスタンスを作成し、それを Web ビューのデリゲートとして割り当てることができます。
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
について
UIWebView
側では、おそらくこのようなコードがあり、デリゲートが
webViewDidStartLoad:
メッセージは
respondsToSelector:
を作成し、必要に応じて送信してください。
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
デリゲートプロパティ自体は、通常、次のように宣言されます。
weak
(ARCの場合)または
assign
(ARC以前の)オブジェクトのデリゲートは、しばしばそのオブジェクトへの強い参照を保持しているので、retainループを避けることができます。(例えば、ビューコントローラは、それが含むビューのデリゲートであることがよくあります。)
クラスのデリゲートを作成する
独自のデリゲートを定義するには、そのメソッドをどこかで宣言する必要があります。 プロトコルに関するApple Docs . 通常、正式なプロトコルを宣言します。UIWebView.hから言い換えると、このような宣言になります。
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
これは、デリゲートのための特別な型を作成するため、インターフェースや抽象ベースクラスと類似しています。
UIWebViewDelegate
この場合 デリゲート実装者はこのプロトコルを採用しなければならないだろう。
@interface MyClass <UIWebViewDelegate>
// ...
@end
そして、プロトコルにあるメソッドを実装します。プロトコルの中で次のように宣言されたメソッドについては
@optional
(ほとんどのデリゲートメソッドと同様) でチェックする必要があります。
-respondsToSelector:
で特定のメソッドを呼び出す前に、そのメソッドの
ネーミング
デリゲートメソッドの名前は通常、デリゲートクラス名で始まり、デリゲートオブジェクトを最初のパラメータとして取ります。また、will-, should-, did- という形式がよく使われます。つまり
webViewDidStartLoad:
(最初のパラメータはウェブビュー) ではなく
loadStarted
(パラメータを取らない)などです。
スピードの最適化
デリゲートがセレクタに応答するかどうかをメッセージのたびにチェックする代わりに、デリゲートが設定されたときにその情報をキャッシュすることができます。これを行う非常にクリーンな方法のひとつは、以下のようにビットフィールドを使用することです。
@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end
@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end
@implementation Something {
struct {
unsigned int didFinishLoadingItem:1;
unsigned int didFailWithError:1;
} delegateRespondsTo;
}
@synthesize delegate;
- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
if (delegate != aDelegate) {
delegate = aDelegate;
delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
}
}
@end
次に、ボディにおいて、デリゲートがメッセージを処理することを確認するために
delegateRespondsTo
構造体を送信するのではなく
-respondsToSelector:
を何度も何度も繰り返す。
非公式代議員
プロトコルが存在する以前は、一般的に
カテゴリー
オン
NSObject
を使用して、デリゲートが実装可能なメソッドを宣言します。例えば
CALayer
は、今もこのままです。
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
これはコンパイラに、任意のオブジェクトが
displayLayer:
.
その場合、同じように
-respondsToSelector:
は、このメソッドを呼び出すために、上で説明したようなアプローチをとります。デリゲートはこのメソッドを実装し
delegate
プロパティを指定すれば、それで完了です(プロトコルに準拠することを宣言する必要はありません)。この方法は Apple のライブラリでは一般的なものですが、新しいコードでは上記のようなより現代的なプロトコルアプローチを使うべきでしょう。
NSObject
(オートコンプリートが使いにくくなる)、コンパイラがタイプミスや同様のエラーを警告しにくくなります。
関連
-
[解決済み] Objective-Cの定数
-
[解決済み] キーボードがあるときに、UITextFieldを編集開始時に上に移動させるには?
-
[解決済み] コールバック内で正しい `this` にアクセスする方法
-
[解決済み] カスタムオブジェクトを含むNSMutableArrayをソートするにはどうすればよいですか?
-
[解決済み] Objective-Cで、ある文字列が他の文字列を含んでいるかどうかを調べるにはどうすればよいですか?
-
[解決済み] SwiftからObjective-Cのコードを呼び出すにはどうしたらいいですか?
-
[解決済み] iOSのバージョンを確認する方法を教えてください。
-
[解決済み] CocoaPodsの最新バージョンにアップデートしますか?
-
[解決済み] Swiftの配列を文字列に変換するには?
-
[解決済み】なぜFunc<T>ではなくExpression<Func<T>を使うのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
libc++abi.dylib が NSException 型の捕捉できない例外で終了する理由 エラー
-
[iOS]コンパイルエラー:ld: アーキテクチャ x86_64 のシンボルが見つかりません。
-
[エラー処理】iOSのエラー、アーキテクチャx86_64の未定義シンボルについて
-
XCode のコンパイル例外を解決する clang: error: linker command failed with exit code 1
-
JenkinsがIOSを自動パッケージングしてモミを配布
-
[解決済み] Xcode 12、iOS Simulator用にビルドしても、iOS用にビルドされたオブジェクトファイルでは、アーキテクチャ「arm64」用にリンクされます。
-
[解決済み] UITextFieldのテキスト変更イベント
-
[解決済み] iPhone UITextField - プレースホルダーの文字色を変更する
-
[解決済み] UIDevice uniqueIdentifierは非推奨 - どうしたらいいの?
-
[解決済み] ぼかしの入ったオーバーレイビューの作成