新しい iOS 開発者として、私はついにデリゲートに出くわしました。チュートリアルに従おうとしています: http://gabriel-tips.blogspot.com/2011/05/input-accessory-view-how-to-add-extra.html、しかし、どこにいるのか理解するのが難しい実際のデリゲート メソッドを配置することになっています。
次に、デリゲート メソッドがどのように呼び出されるかについて、簡単な説明を提供してくれる人はいますか?
ありがとう!
新しい iOS 開発者として、私はついにデリゲートに出くわしました。チュートリアルに従おうとしています: http://gabriel-tips.blogspot.com/2011/05/input-accessory-view-how-to-add-extra.html、しかし、どこにいるのか理解するのが難しい実際のデリゲート メソッドを配置することになっています。
次に、デリゲート メソッドがどのように呼び出されるかについて、簡単な説明を提供してくれる人はいますか?
ありがとう!
デリゲートパターンは、緩い結合を可能にする独立したコントローラー間の通信を可能にする便利な方法です。したがって、次のようなパターンがあるとしましょう。
A
/ \
B C
AがBとCをインスタンス化する場所。AからBおよびAからCの間の通信は簡単ですが、BとCの間の通信はどのように行いますか?BからA?CからA?Key-Valueの監視やコールバックのブロックなど、いくつかの異なる方法があります。ただし、ブロックは強力になりつつありますが、委任は依然として最も頻繁に使用されます。
この例では、オブジェクトAがオブジェクトBをインスタンス化してオブジェクトを作成し、そのオブジェクトに情報を入力します。物事を緩めておきたいので、オブジェクトBはどのようにして新しいオブジェクトをAに戻しますか?さて、これらの9つの簡単なステップで、あなたもそれを行うことができます!意味がないかもしれませんが、ClassBから始めましょう…</ p>
// ClassB.h
@protocol ClassBDelegate; //(1)
@interface ClassB : NSObject
@property (nonatomic, weak) id<ClassBDelegate>bDelegate; //(2)
-(void)makeNewObjectAndSendBack;
@end
@protocol ClassBDelegate : NSObject //(3)
-(void) classB:(Class B *)theClassB finishedWithObject:(id)finishedObject; //(4)
@end
ClassB.m
@implementation
@synthesize bDelegate = _bDelegate; //(5)
-(void)makeNewObjectAndSendBack {
//something something something
[self.bDelegate classB:self finishedWithObject:newObject]; //(6)
}
@end
// ClassA.h
@interface ClassA : NSObject <ClassBDelegate> //(7)
@property (nonatomic, strong) ClassB theClassB;
-(void)yourMethodToDoSomething;
@end
ClassA.m
@implementation
@synthesize theClassB = _theClassB;
-(void)randomMethod {
self.theClassB = [ClassB new];
self.theClassB.bDelegate = self; //(8)
[self.theClassB makeNewObjectAndSendBack];
}
-(void) classB:(Class B *)theClassB finishedWithObject:(id)finishedObject { //(9)
[self doSomethingWithFinishedObject:finishedObject]; //ta-da!
}
@end
7.ClassBDelegateプロトコルに準拠します。これは基本的に、プロトコル定義で定義されたメソッドを実装することを意味します。
8.classBオブジェクトのデリゲートオブジェクトをselfとして設定します。これは非常に重要で、しばしばスキップされます。
9.新しいオブジェクトを取り戻すときのデリゲートメソッドを実装します。
つまり、プロセスは次のとおりです。AインスタントB。AはBのデリゲートを自分自身として設定します。AはBに何かをするように指示します。Bは何かを行い、デリゲートメソッドを介してオブジェクトを送り返します。Aはそれを取り戻します。
プロトコルで何ができるかなど、詳細については、以下を確認してください。BigNerdRanchがプロトコルについて語る パート1 パート2 パート3
幸運を!
デリゲートは、単に別のクラスで作業することに同意するクラスです。デリゲートメソッドは、デリゲートクラスによって呼び出されます。したがって、デリゲートは適切なメソッドの実装を提供する必要があります。テーブルビューを備えたシンプルなビューコントローラを作成しましょう。
// MyViewController.h
@interface MyViewController : UIViewController <UITableViewDelegate>
@property (nonatomic, retain) UITableView *myTableView;
@end
ここMyViewController.hファイルで、ビューコントローラをタイプUITableViewDelegateのデリゲートとして宣言しました(これは、実際にはUITableViewDelegateプロトコルを実装していることを意味します。これについては後で詳しく説明します)。したがって、ViewControllerへの要求に応答することに同意しました。リクエストは、myTableViewと呼ばれるテーブルビューから送信されます。ただし、UITableViewDelegateに準拠していると述べただけでは、ビューコントローラは何の委任にもなりません。私はそれを直接指定しなければなりません:
// MyViewController.m
#import "MyViewController.h"
@implementation MyViewController
- (void)loadView
{
myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
myTableView.delegate = self;
self.view = myTableView;
}
@end
ここでは、MyViewControllerをmyTableViewのデリゲートとして具体的に設定します。これで、テーブルビューがデリゲートに何かを実行するように要求するたびに、そのメッセージがビューコントローラに送信されます。したがって、MyViewControllerは適切なデリゲートメソッドの実装を提供する必要があります。
// MyViewController.m
#import "MyViewController.h"
@implementation MyViewController
- (void)loadView
{
myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
myTableView.delegate = self;
self.view = myTableView;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Selected section:%i row:%i", indexPath.section, indexPath.row);
}
@end
ここでは、デリゲートメソッドtableView:didSelectRowAtIndexPath:の実装を提供しました。これは、適切な場合(ユーザーが行を選択した場合)にmyTableViewによって呼び出されます。
ここでは、UITableViewDelegateで定義されているすべてのデリゲートメソッドを見つけることができます。必須のものとオプションのものがあります。
クラスのデリゲートになるには、実装を提供するために必要なメソッドを知っておく必要があります。
独自のデリゲート定義を作成する場合は、新しいプロトコルを作成します。デリゲートを保持しません(プロパティ宣言を参照)。これにより、保持サイクルが作成されます。
// MyViewController.h
@class MyViewController;
@protocol MyViewControllerDelegate
- (void)viewController:(MyViewController *)viewController didChangeSelection:(NSIndexPath *)newIndexPath;
@end
@interface MyViewController : UIViewController <UITableViewDelegate>
@property (nonatomic, retain) UITableView *myTableView;
@property (nonatomic, assign) id<MyViewControllerDelegate> delegate;
@end
ここで、新しいプロトコルを作成しました。viewController:didChangeSelection:メッセージに応答したいクラスは、これで応答できるようになりました。上記のテーブルビューと同様に、デリゲートをそれ自体に設定してから、メソッドを実装します。デリゲートができたので、適切なタイミングでメソッドを呼び出すことができます。
// MyViewController.m
#import "MyViewController.h"
@implementation MyViewController
- (void)loadView
{
myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
myTableView.delegate = self;
self.view = myTableView;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"Selected section:%i row:%i", indexPath.section, indexPath.row);
indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
[self.delegate viewController:self didChangeSelection:indexPath];
}
@end
これで、デリゲートはメッセージを受信し、ViewControllerが選択を変更したことを知って必要なことを実行できます。