我知道委托是如何工作的,也知道如何使用它们。
但是我如何创建它们呢?
我知道委托是如何工作的,也知道如何使用它们。
但是我如何创建它们呢?
当前回答
ViewController。h
@protocol NameDelegate <NSObject>
-(void)delegateMEthod: (ArgType) arg;
@end
@property id <NameDelegate> delegate;
ViewController。m
[self.delegate delegateMEthod: argument];
MainViewController.m
ViewController viewController = [ViewController new];
viewController.delegate = self;
方法:
-(void)delegateMEthod: (ArgType) arg{
}
其他回答
Objective-C委托是一个对象,它被分配给另一个对象的委托属性。要创建一个委托协议,您需要定义一个实现感兴趣的委托方法的类,并将该类标记为实现委托协议。
例如,假设你有一个UIWebView。如果你想实现它的委托的webViewDidStartLoad:方法,你可以创建一个这样的类:
@interface MyClass<UIWebViewDelegate>
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
然后你可以创建一个MyClass的实例,并将它分配为web视图的委托:
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
在UIWebView端,它可能有类似的代码来查看委托是否响应webViewDidStartLoad:消息使用respondsToSelector:并在适当的情况下发送它。
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
委托属性本身通常声明为weak(在ARC中)或assign(在ARC之前),以避免保留循环,因为对象的委托通常持有对该对象的强引用。(例如,视图控制器通常是它所包含的视图的委托。)
为你的类创建委托
要定义你自己的委托,你必须在某个地方声明它们的方法,就像Apple Docs中关于协议的讨论一样。您通常声明一个正式的协议。这个声明,转述自UIWebView.h,看起来像这样:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
这类似于接口或抽象基类,因为它为你的委托创建了一个特殊类型,在本例中是UIWebViewDelegate。委托实现者必须采用这个协议:
@interface MyClass <UIWebViewDelegate>
// ...
@end
然后实现协议中的方法。对于在协议中声明为@optional的方法(像大多数委托方法一样),在对其调用特定方法之前,需要使用-respondsToSelector:检查。
命名
委托方法通常以委托类名开始命名,并将委托对象作为第一个参数。他们也经常使用will-, should-或did-形式。因此,webViewDidStartLoad:(第一个参数是web视图)而不是loadStarted(不带参数)为例。
速度优化
你可以在设置委托时缓存该信息,而不是在每次我们想要发送消息时检查委托是否响应选择器。一种非常简洁的方法是使用位域,如下所示:
@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end
@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end
@implementation Something {
struct {
unsigned int didFinishLoadingItem:1;
unsigned int didFailWithError:1;
} delegateRespondsTo;
}
@synthesize delegate;
- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
if (delegate != aDelegate) {
delegate = aDelegate;
delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
}
}
@end
然后,在主体中,我们可以通过访问delegateRespondsTo结构体来检查委托是否处理消息,而不是通过反复发送-respondsToSelector:。
非正式代表
在协议出现之前,通常在NSObject上使用category来声明委托可以实现的方法。例如,CALayer仍然这样做:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
这告诉编译器任何对象都可以实现displayLayer:。
然后使用上面描述的相同的-respondsToSelector:方法来调用该方法。委托实现此方法并分配委托属性,仅此而已(没有声明您符合协议)。这种方法在苹果的库中很常见,但是新的代码应该使用上面的更现代的协议方法,因为这种方法会污染NSObject(这使得自动补全不那么有用),并且很难让编译器警告你打字错误和类似的错误。
要创建自己的委托,首先需要创建一个协议并声明必要的方法,而不需要实现。然后在你的头类中实现这个协议在你想要实现委托或委托方法的地方。
协议必须声明如下:
@protocol ServiceResponceDelegate <NSObject>
- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;
@end
这是应该在其中执行某些任务的服务类。它展示了如何定义委托以及如何设置委托。在任务完成后的实现类中,调用委托的方法。
@interface ServiceClass : NSObject
{
id <ServiceResponceDelegate> _delegate;
}
- (void) setDelegate:(id)delegate;
- (void) someTask;
@end
@implementation ServiceClass
- (void) setDelegate:(id)delegate
{
_delegate = delegate;
}
- (void) someTask
{
/*
perform task
*/
if (!success)
{
[_delegate serviceDidFailWithRequestType:@”task failed”];
}
else
{
[_delegate serviceDidFinishedSucessfully:@”task success”];
}
}
@end
这是通过将委托设置为自身来调用服务类的主视图类。协议也是在头类中实现的。
@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}
- (void) go;
@end
@implementation viewController
//
//some methods
//
- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}
就是这样,通过在这个类中实现委托方法,一旦操作/任务完成,控制就会回来。
拜托!查看下面的简单一步一步的教程,了解委托如何在iOS中工作。
iOS中的委托
我已经创建了两个viewcontroller(用于从一个视图控制器发送数据到另一个视图控制器)
FirstViewController实现委托(提供数据)。 SecondViewController声明委托(它将接收数据)。
假设你有一个你开发的类,想要声明一个委托属性,以便在发生一些事件时能够通知它:
@class myClass;
@protocol myClassDelegate <NSObject>
-(void)myClass:(MyClass*)myObject requiredEventHandlerWithParameter:(ParamType*)param;
@optional
-(void)myClass:(MyClass*)myObject optionalEventHandlerWithParameter:(ParamType*)param;
@end
@interface MyClass : NSObject
@property(nonatomic,weak)id< MyClassDelegate> delegate;
@end
so you declare a protocol in MyClass header file (or a separate header file) , and declare the required/optional event handlers that your delegate must/should implement , then declare a property in MyClass of type (id< MyClassDelegate>) which means any objective c class that conforms to the protocol MyClassDelegate , you'll notice that the delegate property is declared as weak , this is very important to prevent retain cycle (most often the delegate retains the MyClass instance so if you declared the delegate as retain, both of them will retain each other and neither of them will ever be released).
你还会注意到协议方法将MyClass实例作为参数传递给委托,这是最好的实践,以防委托想要调用MyClass实例上的一些方法,也有助于当委托将自己声明为MyClassDelegate到多个MyClass实例时,就像当你的ViewController中有多个UITableView的实例并将自己声明为UITableViewDelegate到所有这些实例时。
在你的MyClass中,你用声明的事件通知委托,如下所示:
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
你首先检查你的委托是否响应你即将调用的协议方法,以防委托没有实现它,应用程序将崩溃(即使协议方法是必需的)。
我认为一旦你理解了委托,所有这些答案都很有意义。就我个人而言,我来自C/ c++的土地,在此之前,像Fortran等过程语言,所以这里是我在c++范式中寻找类似类似物的2分钟。
如果我要向c++ /Java程序员解释委托,我会说
什么是委托? 这些是指向另一个类中的类的静态指针。一旦你分配了一个指针,你就可以调用该类中的函数/方法。因此,类的一些函数被“委托”(在c++中,由类对象指针指向的指针)给另一个类。
什么是协议? 从概念上讲,它的作用与你作为委托类分配的类的头文件类似。协议是一种显式的方式,用于定义在类中需要实现哪些方法,而该类的指针被设置为类中的委托。
How can I do something similar in C++? If you tried to do this in C++, you would by defining pointers to classes (objects) in the class definition and then wiring them up to other classes that will provide additional functions as delegates to your base class. But this wiring needs to be maitained within the code and will be clumsy and error prone. Objective C just assumes that programmers are not best at maintaining this decipline and provides compiler restrictions to enforce a clean implementation.