web-dev-qa-db-ja.com

Objective CのiPhone開発における「デリゲート」とは何ですか?

Objective CのiPhone開発における「デリゲート」とは何ですか?

69
MikeN

こちらをご覧ください discussion

デリゲートを使用すると、イベントが発生したときに、あるオブジェクトが別のオブジェクトにメッセージを送信できます。たとえば、 NSURLConnectionクラス を使用してWebサイトからデータを非同期でダウンロードする場合。 NSURLConnectionには、3つの一般的なデリゲートがあります。

 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
 - (void)connectionDidFinishLoading:(NSURLConnection *)connection
 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

NSURLConnectionがエラーに遭遇した場合、正常に終了した場合、またはWebサイトから応答を受信した場合、これらのデリゲートの1つ以上がそれぞれ呼び出されます。

55
Jordan

デリゲートは、デリゲートホルダーが呼び出す方法を知っている一連のメソッドを持つオブジェクトへのポインタです。つまり、後で作成されるオブジェクトから特定のコールバックを有効にするメカニズムです。

良い例はUIAlertViewです。 UIAlertViewオブジェクトを作成して、ユーザーに短いメッセージボックスを表示し、「OK」や「Cancel」などの2つのボタンを選択できるようにします。 UIAlertViewにはコールバックする方法が必要ですが、コールバックするオブジェクトとコールするメソッドの情報はありません。

この問題を解決するには、selfへのポインターをデリゲートオブジェクトとしてUIAlertViewに送信し、その代わりに(オブジェクトのヘッダーファイルでUIAlertViewDelegateを宣言することで)同意しますalertView:clickedButtonAtIndex:など、UIAlertViewが呼び出すことができるメソッドを実装します。

this post をご覧ください。デリゲートデザインパターンおよびその他のコールバックテクニックの簡単な高レベルイントロです

参照:

78
Tyler

デリゲートはデザインパターンです。特別な構文や言語のサポートはありません。

デリゲートは、特定の事態が発生したときに別のオブジェクトがメッセージを送信するオブジェクトであるため、元のオブジェクトが設計されていないアプリ固有の詳細を処理できます。これは、サブクラス化せずに動作をカスタマイズする方法です。

20
MikeN

このウィキペディアの記事で最もよく説明されていると思います: http://en.wikipedia.org/wiki/Delegation_pattern

これは設計パターンの「単なる」実装であり、Objective-Cでは非常に一般的です

5
Felix Kling

お願いします!以下の簡単なステップバイステップチュートリアルをチェックして、デリゲートがiOSでどのように機能するかを理解してください。

iOSのデリゲート

2つのViewControllerを作成しました(一方から他方にデータを送信するため)

  1. FirstViewControllerはデリゲート(データを提供する)を実装します。
  2. SecondViewControllerは、デリゲート(データを受け取る)を宣言します。

以下にサンプルコードを示します。

AppDelegate.h


#import <UIKit/UIKit.h>

@class FirstViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) FirstViewController *firstViewController;

@end

AppDelegate.m


#import "AppDelegate.h"
#import "FirstViewController.h"

@implementation AppDelegate

@synthesize firstViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    //create instance of FirstViewController
    firstViewController = [[FirstViewController alloc] init];

    //create UINavigationController instance using firstViewController
    UINavigationController *firstView = [[UINavigationController alloc] initWithRootViewController:firstViewController];

    //added navigation controller to window as a rootViewController
    self.window.rootViewController = firstView;

    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

FirstViewController.h


#import <UIKit/UIKit.h>
#import "SecondViewController.h"

@interface FirstViewController : UIViewController<MyDelegate>

@property (nonatomic, retain) NSString *mesasgeData;

@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet UIButton *nextButton;

- (IBAction)buttonPressed:(id)sender;

@property (nonatomic, strong) SecondViewController *secondViewController;

@end

FirstViewController.m


#import "FirstViewController.h"

@interface FirstViewController ()
@end

@implementation FirstViewController

@synthesize mesasgeData;
@synthesize textField;
@synthesize secondViewController;

#pragma mark - View Controller's Life Cycle methods

- (void)viewDidLoad
{
    [super viewDidLoad];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

#pragma mark - Button Click event handling method

- (IBAction)buttonPressed:(id)sender {

    //get the input data from text feild and store into string
    mesasgeData = textField.text;

    //go keypad back when button clicked from textfield
    [textField resignFirstResponder];

    //crating instance of second view controller
    secondViewController = [[SecondViewController alloc]init];

    //it says SecondViewController is implementing MyDelegate
    secondViewController.myDelegate = self;

    //loading new view via navigation controller
    [self.navigationController pushViewController:secondViewController animated:YES];    
}

#pragma mark - MyDelegate's method implementation

-(NSString *) getMessageString{
    return mesasgeData;
}

@end

SecondViewController.h


//declare our own delegate
@protocol MyDelegate <NSObject>

-(NSString *) getMessageString;

@end

#import <UIKit/UIKit.h>

@interface SecondViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *messageLabel;

@property (nonatomic, retain) id <MyDelegate> myDelegate;

@end

SecondViewController.m


#import "SecondViewController.h"

@interface SecondViewController ()
@end

@implementation SecondViewController

@synthesize messageLabel;
@synthesize myDelegate;

- (void)viewDidLoad
{
    [super viewDidLoad];    
    messageLabel.text = [myDelegate getMessageString];    
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end
3
swiftBoy

簡単なプログラムで詳しく説明しよう

2つのクラス

Student.h

_#import <Foundation/Foundation.h>

@interface Student : NSObject
@property (weak) id  delegate;
- (void) studentInfo;
@end
_

Student.m

_#import "Student.h"
@implementation Student
- (void) studentInfo
{
    NSString *teacherName;
    if ([self.delegate respondsToSelector:@selector(teacherName)]) {
        teacherName = [self.delegate performSelector:@selector(teacherName)];
    }
    NSLog(@"\n Student name is XYZ\n Teacher name is %@",teacherName);
}
@end
_

Teacher.h

_#import <Foundation/Foundation.h>
#import "Student.h>

@interface Teacher: NSObject
@property (strong,nonatomic) Student *student;
- (NSString *) teacherName;
- (id) initWithStudent:(Student *)student;
@end
_

Teacher.m

_#import "Teacher.h"

@implementation Teacher

- (NSString *) teacherName
{
    return @"ABC";
}
- (id) initWithStudent:(Student *)student
{
    self = [ super init];
    if (self) {
        self.student = student;
        self.student.delegate = self;
    }
    return self;
}
@end
_

main.m

_#import <Foundation/Foundation.h>
#import "Teacher.h"
int main ( int argc, const char* argv[])
{
    @autoreleasepool {

        Student *student = [[Student alloc] init];
        Teacher *teacher = [[Teacher alloc] initWithStudent:student];

        [student studentInfo];

    }
    return 0;
}
_

[〜#〜]説明[〜#〜] :::

  1. _initWithStudent:student_が実行されるメインメソッドから

    1.1教師のオブジェクトのプロパティ「student」には、学生オブジェクトが割り当てられます。

    1.2 _self.student.delegate = self_

    _    means student object's delegate will points to teacher object
    _
  2. _[student studentInfo]_が呼び出されるときのメインメソッドから

    2.1 [self.delegate respondToSelector:@selector(teacherName)]ここでは、デリゲートはすでに教師オブジェクトを指しているため、 'teacherName'インスタンスメソッドを呼び出すことができます。

    2.2 [self.delegate performSelector:@selector(teacherName)]は簡単に実行されます。

TeacherオブジェクトがStudentオブジェクトにデリゲートを割り当て、独自のメソッドを呼び出すように見えます。

teacherName」メソッドと呼ばれる学生オブジェクトが表示されますが、基本的には教師オブジェクト自体によって行われます。

3
Milan Kamilya

デリゲートを理解すれば、これらの答えはすべて理にかなっていると思います。個人的にはC/C++の国から来ました。Fortranなどの手続き型言語の前に来たので、C++パラダイムで類似の類似物を見つけるための2分間の取り組みを紹介します。

C++/Javaプログラマーへのデリゲートを説明する場合、私は言うでしょう

デリゲートとは何ですか?これらは、別のクラス内のクラスへの静的ポインターです。ポインターを割り当てたら、そのクラスの関数/メソッドを呼び出すことができます。したがって、クラスの一部の関数は別のクラスに「委任」されます(C++の世界では、クラスオブジェクトポインターによるポインター)。

プロトコルとは何ですか?概念的には、デリゲートクラスとして割り当てるクラスのヘッダーファイルと同様の目的として機能します。プロトコルは、クラス内でデリゲートとして設定されたポインターのクラスで実装する必要があるメソッドを定義する明示的な方法です。

C++で同様のことを行うにはどうすればよいですか? C++でこれを実行しようとした場合、クラス定義でクラス(オブジェクト)へのポインターを定義し、基本クラスへのデリゲートとして追加機能を提供する他のクラスにそれらを接続します。ただし、この配線はコード内で維持する必要があり、扱いにくくエラーが発生しやすくなります。 Objective Cは、プログラマーがこの規律を維持するのが最善ではないと想定し、クリーンな実装を実施するためのコンパイラー制限を提供します。

2
DrBug

デリゲートはオブジェクトCで自動イベントを起動します。デリゲートをオブジェクトに設定すると、デリゲートメソッドを介して別のオブジェクトにメッセージが送信されます。

これは、サブクラス化を必要とせずにクラスの動作を変更する方法です。

デリゲートメソッドを持つ各オブジェクト。これらのデリゲートメソッドは、特定のオブジェクトがユーザーインタラクションとプログラムフローサイクルに参加すると起動します。

簡単に言うと、委任とは、オブジェクト間の強い相互依存関係を作成せずに、オブジェクトが相互に対話できるようにする方法です。

1
Arunjack

デリゲートは、ユーザーのテーピングアクションをキャプチャし、ユーザーのテーピングアクションに従って特定のアクションを実行します。

1
Teja Swaroop

デリゲートはオブジェクトのインスタンスに過ぎず、オブジェクトの代わりにメソッドを呼び出すことができます。また、そのオブジェクトの実行時にメソッドを作成するのに役立ちます。

0
Madhu