Objective C 的 iPhone 开发中的“代表”是什么?
10 回答
委托是指向具有一组方法的对象的指针,委托持有者知道如何调用。换句话说,它是一种从后来创建的对象启用特定回调的机制。
一个很好的例子是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 遇到失败、成功完成或收到来自网站的响应时,将分别调用这些委托中的一个或多个。
代表是一种设计模式;没有特殊的语法或语言支持。
委托只是当某些事情发生时另一个对象向其发送消息的对象,因此委托可以处理原始对象未设计用于的特定于应用程序的细节。这是一种无需子类化即可自定义行为的方式。
我认为这篇维基百科文章描述得最好:http ://en.wikipedia.org/wiki/Delegation_pattern
它“只是”一种设计模式的实现,在 Objective-C 中很常见
请!查看下面的简单分步教程,了解 Delegates 在 iOS 中的工作原理。
我创建了两个 ViewController(用于将数据从一个发送到另一个)
- FirstViewController 实现委托(提供数据)。
- 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
第一视图控制器.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
第一视图控制器.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
第二视图控制器.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/C++ 领域,之前是 Fortran 等过程语言,所以这是我在 C++ 范式中寻找类似类似物的 2 分钟尝试。
如果我要向 C++/Java 程序员解释委托,我会说
什么是代表?这些是指向另一个类中的类的静态指针。分配指针后,您可以调用该类中的函数/方法。因此,您的类的某些功能被“委托”(在 C++ 世界中 - 类对象指针指向的指针)到另一个类。
什么是协议?从概念上讲,它的用途与您分配为委托类的类的头文件类似。协议是定义需要在类中实现哪些方法的显式方式,该类的指针被设置为类中的委托。
如何在 C++ 中做类似的事情?如果您尝试在 C++ 中执行此操作,您将通过在类定义中定义指向类(对象)的指针,然后将它们连接到其他类,这些类将提供附加功能作为基类的委托。但是这种接线需要在代码中维护,并且会很笨拙且容易出错。Objective C 只是假设程序员并不擅长维护这一原则,并提供编译器限制来强制执行干净的实现。
我尝试通过简单的程序来详细说明
两班
学生.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property (weak) id delegate;
- (void) studentInfo;
@end
学生.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
老师.h
#import <Foundation/Foundation.h>
#import "Student.h>
@interface Teacher: NSObject
@property (strong,nonatomic) Student *student;
- (NSString *) teacherName;
- (id) initWithStudent:(Student *)student;
@end
老师.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
主文件
#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
means student object's delegate will points to teacher object
[student studentInfo]
何时调用main 方法2.1
[self.delegate respondToSelector:@selector(teacherName)]
这里的委托已经指向了教师对象,所以它可以调用'teacherName'实例方法。2.2 所以
[self.delegate performSelector:@selector(teacherName)]
会很容易执行。
看起来教师对象将委托分配给学生对象以调用它自己的方法。
这是一个相对的想法,我们看到学生对象称为' teacherName '方法,但它基本上是由教师对象本身完成的。
委托触发 Objects C 中的自动事件。如果将委托设置为 Object,它会通过委托方法将消息发送到另一个对象。
这是一种无需子类化即可修改类行为的方法。
每个对象都有委托方法。这些委托方法在特定对象参与用户交互和程序流程循环时触发。
简单地说:委托是一种允许对象相互交互而不在它们之间创建强相互依赖关系的方式。
委托捕获用户的点击动作,并根据用户的点击动作执行特定的动作。
委托只不过是对象的实例,我们可以代表该对象调用方法。并且还有助于在该对象的 rumtime 中创建方法。