2010-03-28 35 views
65

"Đại biểu" trong sự phát triển iPhone của Objective C là gì?"Đại biểu" trong sự phát triển iPhone của Objective C là gì?

+0

Điều này có vẻ trùng lặp với http://stackoverflow.com/questions/1349706/little-confused-on-delegates-in-objective-c và có thể http://stackoverflow.com/questions/1788032/what -người được ủy quyền-và-đại biểu-phương pháp –

+0

Xem thêm: http://stackoverflow.com/questions/645449/how-to-use-custom-delegates-in-objective-c, http://stackoverflow.com/ câu hỏi/626898/how-do-i-create-delegates-in-objective-c, http://stackoverflow.com/questions/1015608/how-to-perform-callbacks-in-objective-c và http://stackoverflow.com/questions/1408774/can-someone-explain-what-a-delegate-is-with-an-example –

Trả lời

55

Xem này discussion

Một đại biểu cho phép một đối tượng để gửi tin nhắn đến một đối tượng khác khi một sự kiện xảy ra. Ví dụ: nếu bạn đang tải xuống dữ liệu từ một trang web không đồng bộ bằng cách sử dụng NSURLConnection class. NSURLConnection có ba đại biểu chung:

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

Một hoặc nhiều các đại biểu sẽ được gọi khi NSURLConnection gặp một thất bại, kết thúc thành công, hoặc nhận được phản hồi từ các trang web tương ứng.

+4

Đây có phải là loại người nghe giống như trong Android? –

+0

@JordanHochstetler trông giống như đại biểu chính xác là người nghe –

19

Đại biểu là mẫu thiết kế; không có hỗ trợ ngôn ngữ hoặc cú pháp đặc biệt.

Một đại biểu chỉ là một đối tượng mà một đối tượng khác gửi tin nhắn đến khi một số điều xảy ra, để đại biểu có thể xử lý chi tiết ứng dụng cụ thể mà đối tượng gốc không được thiết kế. Đó là một cách tùy biến hành vi mà không có phân lớp phụ.

+2

Vì vậy, về cơ bản nó là OOP-cách thực hiện một cuộc gọi lại? –

+0

@DanielSloof Tôi đã suy nghĩ tương tự ... – Mirko

77

Một đại biểu là một con trỏ đến một đối tượng với một tập hợp các phương thức mà người nắm giữ đại biểu biết cách gọi. Nói cách khác, nó là một cơ chế để cho phép gọi lại cụ thể từ một đối tượng được tạo sau này.

A ví dụ tốt là UIAlertView. Bạn tạo một đối tượng UIAlertView để hiển thị hộp thư ngắn cho người dùng, có thể cho họ lựa chọn bằng hai nút như "OK" và "Hủy". UIAlertView cần một cách để gọi lại cho bạn nhưng không có thông tin về đối tượng nào cần gọi lại và phương thức cần gọi.

Để giải quyết vấn đề này, bạn có thể gửi con trỏ self của bạn để UIAlertView như một đối tượng delegate, và đổi lại bạn đồng ý (bằng cách tuyên bố các UIAlertViewDelegate trong tập tin tiêu đề của đối tượng của bạn) để thực hiện một số phương pháp mà UIAlertView có thể gọi điện thoại, chẳng hạn như alertView:clickedButtonAtIndex: .

Kiểm tra this post cho phần giới thiệu cấp cao nhanh cho mẫu thiết kế đại biểu và các kỹ thuật gọi lại khác.

Tài liệu tham khảo:

1

Các đại biểu bắn các sự kiện tự động trong các đối tượng C. Nếu bạn đặt các đại biểu đến Object, nó sẽ gửi thông điệp tới một đối tượng khác thông qua các phương thức ủy nhiệm.

Đó là cách để sửa đổi hành vi của một lớp mà không yêu cầu phân lớp phụ.

Mỗi đối tượng có phương thức đại biểu.Các phương thức ủy nhiệm này sẽ kích hoạt, khi các đối tượng cụ thể tham gia vào tương tác người dùng và chu trình dòng chương trình.

Nói một cách đơn giản: ủy quyền là cách cho phép các đối tượng tương tác với nhau mà không tạo sự phụ thuộc lẫn nhau mạnh mẽ giữa chúng.

1

Một đại biểu nắm bắt các hành động chạm của người dùng và thực hiện Hành động cụ thể theo hành động Nhấn vào người dùng.

0

Đại biểu không là gì ngoài trường hợp đối tượng mà chúng ta có thể gọi phương thức thay mặt cho đối tượng đó. và cũng giúp tạo ra các phương pháp trong thời gian truyền tin của các đối tượng đó.

3

Xin vui lòng! kiểm tra dưới đây hướng dẫn từng bước đơn giản để hiểu cách Delegates hoạt động trong iOS.

Delegate in iOS

Tôi đã tạo ra hai ViewControllers (để gửi dữ liệu từ một đến khác)

  1. FirstViewController thi đại biểu (trong đó cung cấp dữ liệu).
  2. SecondViewController khai báo đại biểu (sẽ nhận dữ liệu).

Đây là mã mẫu có thể giúp bạn.

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 
+0

Xin chào RDC, mã này không hoạt động, bạn có thể vui lòng thử một lần cuối cùng không. –

2

Tôi nghĩ rằng tất cả những câu trả lời làm cho rất nhiều ý nghĩa khi bạn hiểu các đại biểu. Cá nhân tôi đến từ vùng đất của C/C++ và trước đó ngôn ngữ thủ tục như Fortran vv vì vậy đây là 2 phút của tôi đi vào việc tìm kiếm tương tự tương tự trong mô hình C + +.

Nếu tôi giải thích đại biểu cho lập trình viên C++/Java, tôi sẽ nói

Đại biểu là gì? Đây là các con trỏ tĩnh tới các lớp trong lớp khác. Khi bạn gán một con trỏ, bạn có thể gọi các hàm/phương thức trong lớp đó. Do đó một số chức năng của lớp học của bạn được "ủy nhiệm" (Trong C++ thế giới - con trỏ đến bởi một con trỏ đối tượng lớp) đến một lớp khác.

Giao thức là gì? Về mặt khái niệm, nó đóng vai trò tương tự như tệp tiêu đề của lớp bạn đang gán làm lớp đại biểu. Một giao thức là một cách rõ ràng để xác định những phương thức nào cần được thực hiện trong lớp của người mà con trỏ được đặt làm đại biểu trong một lớp.

Tôi có thể làm điều gì đó tương tự trong C++? Nếu bạn đã cố gắng làm điều này trong C++, bạn sẽ định nghĩa con trỏ tới các lớp (đối tượng) trong định nghĩa lớp và sau đó nối chúng với các lớp khác sẽ cung cấp các hàm bổ sung làm đại biểu cho lớp cơ sở của bạn. Nhưng hệ thống dây điện này cần được giữ trong mã và sẽ dễ bị vụng về và dễ bị lỗi. Mục tiêu C chỉ giả định rằng các lập trình viên không phải là giỏi nhất trong việc duy trì quy tắc này và cung cấp các hạn chế của trình biên dịch để thực thi việc thực hiện sạch.

3

tôi cố gắng xây dựng nó thông qua chương trình đơn giản

Hai Lớp

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; 
} 

GIẢI THÍCH :::

  1. Từ phương pháp chính khi initWithStudent:student sẽ thực hiện

    1.1 Tài sản của đối tượng giáo viên 'sinh viên' sẽ được chỉ định với đối tượng sinh viên.

    1,2 self.student.delegate = self

    means student object's delegate will points to teacher object 
    
  2. Từ phương pháp chính khi [student studentInfo] sẽ được gọi

    2.1 [self.delegate respondToSelector:@selector(teacherName)] Ở đây đại biểu đã trỏ đến đối tượng giáo viên để nó có thể gọi phương thức cá thể 'teacherName'.

    2.2 vì vậy [self.delegate performSelector:@selector(teacherName)] sẽ thực thi dễ dàng.

Có vẻ như đối tượng giáo viên chỉ định đại biểu cho đối tượng sinh viên gọi đó là phương pháp riêng.

Đó là một ý tưởng tương đối, nơi chúng tôi thấy đối tượng sinh viên được gọi là phương pháp 'teacherName' nhưng về cơ bản được thực hiện bởi chính đối tượng giáo viên.

Các vấn đề liên quan