在Objective-C的iPhone开发中,“delegate”是什么意思?
在Objective-C的iPhone开发中,“delegate”是什么意思?
委托是一个指向一组方法的对象的指针,委托持有者知道如何调用这些方法。换句话说,它是一种使后创建的对象能够进行特定回调的机制。
一个很好的例子是UIAlertView
。您可以创建一个UIAlertView
对象来向用户显示一个短消息框,可能还会提供两个按钮“确定”和“取消”的选择。 UIAlertView
需要一种方式来回调您,但它不知道要回调哪个对象以及调用哪个方法。
为解决这个问题,您可以将 self
指针作为委托对象发送到 UIAlertView
中,并且通过在对象的头文件中声明 UIAlertViewDelegate
来实现一些方法,以便UIAlertView
可以调用,例如alertView:clickedButtonAtIndex:
。
请查看此帖子,了解有关委托设计模式和其他回调技术的快速高级介绍。
参考文献:
请看这个讨论
委托模式允许一个对象在事件发生时向另一个对象发送消息。例如,如果您使用NSURLConnection类异步地从网站下载数据,则可以使用代理模式来监听下载进度。NSURLConnection有三个常见的代理:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
这些代理中的一个或多个将在NSURLConnection遇到故障、成功完成或从网站收到响应时被调用。
委托是一种设计模式;没有特殊的语法或语言支持。
委托只是另一个对象在发生某些事情时发送消息的对象,以便委托可以处理原始对象未设计的应用程序特定细节。这是一种避免子类化的自定义行为的方式。
我将通过一个简单的程序来详细说明它
两个类
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;
}
解释 :::
From main method when initWithStudent:student
will execute
1.1 Teacher's object's property 'student' will be assigned with student object.
1.2 self.student.delegate = self
means student object's delegate will points to teacher object
From main method when [student studentInfo]
will be called
2.1 [self.delegate respondToSelector:@selector(teacherName)]
Here delegate already points to teacher object so it can invoke
'teacherName' instance method.
2.2 so [self.delegate performSelector:@selector(teacherName)]
will execute easily.
我创建了两个视图控制器(用于从一个视图控制器向另一个视图控制器发送数据)。
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
委托在C对象中触发自动事件。如果将委托设置为对象,则通过委托方法将消息发送到另一个对象。
这是一种在不需要子类化的情况下修改类行为的方式。
每个对象都有委托方法。当特定对象参与用户交互和程序流程周期时,这些委托方法会触发。
简单地说:委托是一种允许对象相互交互而不创建强依赖关系的方式。
委托是一个对象的实例,我们可以代表该对象调用方法。它还有助于在对象运行时创建方法。