Objective C的iPhone开发中的“委托”是什么?

时间:2010-03-28 18:54:38

标签: ios iphone objective-c delegates uiapplicationdelegate

Objective C的iPhone开发中的“委托”是什么?

10 个答案:

答案 0 :(得分:77)

委托是指向对象的指针,该对象具有委托人知道如何调用的一组方法。换句话说,它是一种从后来创建的对象中启用特定回调的机制。

一个好例子是UIAlertView 。您创建一个UIAlertView对象以向用户显示一个短消息框,可能会为他们提供两个按钮,如“确定”和“取消”。 UIAlertView需要一种方法来回叫,但它没有关于回叫哪个对象以及调用哪种方法的信息。

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

查看this post 代表设计模式及其他回调技巧的快速高级介绍

参考文献:

答案 1 :(得分:55)

请参阅此discussion

委托允许一个对象在事件发生时将消息发送到另一个对象。例如,如果您使用NSURLConnection class以异步方式从网站下载数据。 NSURLConnection有三个共同的代表:

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

当NSURLConnection遇到故障,成功完成或从网站收到响应时,将会调用这些代理中的一个或多个。

答案 2 :(得分:20)

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

委托只是另一个对象在发生某些事情时发送消息的对象,因此委托可以处理原始对象不适用的特定于应用程序的详细信息。这是一种在没有子类化的情况下自定义行为的方法。

答案 3 :(得分:5)

我认为这篇维基百科文章最好地描述了它:http://en.wikipedia.org/wiki/Delegation_pattern

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

答案 4 :(得分:3)

请!请查看以下简单的分步教程,了解Delegates如何在iOS中工作。

  

Delegate in iOS

我创建了两个ViewControllers(用于将数据从一个发送到另一个)

  1. FirstViewController实现委托(提供数据)。
  2. SecondViewController声明委托(将接收数据)。
  3. 以下示例代码可以为您提供帮助。

    <强> 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
    

答案 5 :(得分:3)

我尝试通过简单的程序来详细说明

两个班级

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教师对象的属性“学生”将被分配学生对象。

    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)]          将很容易执行。

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

    这是一个相对的想法,我们看到学生对象称为“ teacherName ”方法,但它基本上由教师对象本身完成。

答案 6 :(得分:2)

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

如果我要向C ++ / Java程序员解释代表,我会说

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

什么是协议?从概念上讲,它的作用与您指定为委托类的类的头文件类似。协议是一种明确的方法,用于定义需要在类中实现哪些方法的指针被设置为类中的委托。

我怎样才能在C ++中做类似的事情?如果您尝试在C ++中执行此操作,则可以通过在类定义中定义指向类(对象)的指针,然后将它们连接到其他类,这些类将提供其他函数作为基类的委托。但是这种布线需要在代码中保留,并且会很笨拙且容易出错。 Objective C假设程序员不擅长维护这个decipline并提供编译器限制来强制执行干净的实现。

答案 7 :(得分:1)

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

这是一种修改类行为而无需子类化的方法。

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

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

答案 8 :(得分:1)

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

答案 9 :(得分:0)

Delegate只是Object的实例,我们可以代表该对象调用方法。并且还有助于在对象的朗姆酒中创建方法。