关于ios:Objective C的iPhone开发中的“委托”是什么?

What is a “delegate” in Objective C's iPhone development?

本问题已经有最佳答案,请猛点这里访问。

目标C的iPhone开发中的"代表"是什么?


委托是指向对象的指针,具有委托持有者知道如何调用的一组方法。换言之,它是一种机制,用于启用以后创建的对象的特定回调。

一个很好的例子是UIAlertView。您创建一个UIAlertView对象,向用户显示一个短消息框,可能会给他们一个选择,有两个按钮,如"确定"和"取消"。UIAlertView需要一种方法来回调您,但是它没有关于回调哪个对象和调用什么方法的信息。

为了解决这个问题,您可以将self指针发送到UIAlertView作为委托对象,作为交换条件,您同意(通过在对象的头文件中声明UIAlertViewDelegate来实现UIAlertView可以调用的一些方法,例如alertView:clickedButtonAtIndex:

查看这篇文章,可以快速地对委托设计模式和其他回调技术进行高级介绍。

参考文献:

  • uiAlertView类引用
  • uiAlertViewDelegate类引用
  • 苹果代表和数据源指南

查看此讨论

委托允许一个对象在事件发生时向另一个对象发送消息。例如,如果您正在使用nsurlconnection类从网站异步下载数据。NSURLConnection有三个通用代理:

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

当nsurlconnection分别遇到故障、成功完成或从网站收到响应时,将调用这些委托中的一个或多个。


委托是一种设计模式;没有特殊的语法或语言支持。

委托只是一个对象,当某些事情发生时,另一个对象会向其发送消息,这样委托就可以处理原始对象未设计用于的特定于应用程序的详细信息。这是一种自定义行为而不使用子类化的方法。


我认为这篇维基百科的文章描述得最好:http://en.wikipedia.org/wiki/delegation_pattern

它只是设计模式的一种实现,在Objective-C中非常常见。


我试图通过简单的程序来阐述它

两个班

学生H

1
2
3
4
5
6
#import <Foundation/Foundation.h>

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

学生。

1
2
3
4
5
6
7
8
9
10
11
12
13
#import"Student.h"
@implementation Student
- (void) studentInfo
{
    NSString *teacherName;
    if ([self.delegate respondsToSelector:@selector(teacherName)]) {
        teacherName = [self.delegate performSelector:@selector(teacherName)];
    }
    NSLog(@"
 Student name is XYZ
 Teacher name is %@"
,teacherName);
}
@end

老师,H

1
2
3
4
5
6
7
8
#import <Foundation/Foundation.h>
#import"Student.h>

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

老师。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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

主m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#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;
}

说明:

  • initWithStudent:student将执行时,从主方法

    1.1教师对象的属性"学生"将分配学生对象。

    1.2 self.student.delegate = self

    1
        means student object's delegate will points to teacher object
  • 当调用[student studentInfo]时从主方法

    2.1 [self.delegate respondToSelector:@selector(teacherName)]。这里的委托已经指向教师对象,以便它可以调用"TeacherName"实例方法。

    2.2所以[self.delegate performSelector:@selector(teacherName)]。很容易执行。

  • 它看起来像教师对象将委托分配给学生对象来调用它自己的方法。

    这是一个相对的概念,我们看到学生对象称为"teachername"方法,但它基本上是由老师对象本身完成的。


    拜托!请查看下面的简单分步教程,了解代理如何在iOS中工作。

    Delegate in iOS

    我创建了两个视图控制器(用于将数据从一个发送到另一个)

  • FirstViewController实现委托(提供数据)。
  • secondViewController声明委托(将接收数据)。
  • 这是示例代码可以帮助您。

    AppDealth.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #import <UIKit/UIKit.h>

    @class FirstViewController;

    @interface AppDelegate : UIResponder <UIApplicationDelegate>

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

    @end

    AppDeavig.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #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

    FirstView控制器.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #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

    FirstView控制器.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #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

    第二视图控制器.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //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

    第二视图控制器.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #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


    我认为,一旦你理解了代表的意思,所有这些答案都很有意义。就我个人而言,我来自C/C++的领域,之前的程序语言如Fortran等,所以这是我在C++范例中找到类似的类比的2分钟。

    如果我要解释一个C++程序员的委托,我会说

    代表是什么?这些是指向另一个类中的类的静态指针。分配指针后,可以调用该类中的函数/方法。因此,您的类的一些函数是"委托"(在C++世界中由类对象指针指向)到另一个类。

    什么是协议?从概念上讲,它的作用与作为委托类分配的类的头文件类似。协议是定义需要在类中实现哪些方法的显式方法,这些方法的指针被设置为类中的委托。

    如何在C++中做类似的事情?如果您试图在C++中实现这一点,您将通过定义类定义中的类(对象)指针,然后将它们连接到其他类,这些类将作为委托给基类提供附加功能。但是,这种接线需要在代码中维护,并且将是笨拙和容易出错的。目标C只是假设程序员不擅长维护这个分解,并提供编译器限制来强制执行干净的实现。


    委托捕获用户的录制操作,并根据用户的录制操作执行特定操作。


    委托在对象C中触发自动事件。如果将委托设置为对象,它将通过委托方法将消息发送给另一个对象。

    这是一种在不需要子类化的情况下修改类行为的方法。

    每个对象都有委托方法。当特定对象参与用户交互和程序流循环时,将激发这些委托方法。

    简单地说:委托是一种允许对象彼此交互而不在它们之间产生强烈依赖关系的方式。


    委托只是对象的实例,我们可以代表该对象调用方法。也有助于在rumtime中创建该对象的方法。