我知道委托是如何工作的,也知道如何使用它们。

但是我如何创建它们呢?


当前回答

这并不是问题的答案,但如果你在查找如何创建自己的委托也许一些更简单的东西会是更好的答案。

我很少实现委托,因为我很少需要。对于一个委托对象,我只能有一个委托。所以如果你想让你的委托进行单向通信/传递数据,你最好使用通知。

NSNotification可以将对象传递给多个接收者,它非常容易使用。 它是这样工作的:

MyClass。M文件应该是这样的

#import "MyClass.h"
@implementation MyClass 

- (void) myMethodToDoStuff {
//this will post a notification with myClassData (NSArray in this case)  in its userInfo dict and self as an object
[[NSNotificationCenter defaultCenter] postNotificationName:@"myClassUpdatedData"
                                                    object:self
                                                  userInfo:[NSDictionary dictionaryWithObject:selectedLocation[@"myClassData"] forKey:@"myClassData"]];
}
@end

在其他类中使用通知: 添加类作为观察者:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];

实现选择器:

- (void) otherClassUpdatedItsData:(NSNotification *)note {
    NSLog(@"*** Other class updated its data ***");
    MyClass *otherClass = [note object];  //the object itself, you can call back any selector if you want
    NSArray *otherClassData = [note userInfo][@"myClassData"]; //get myClass data object and do whatever you want with it
}

如果,不要忘记删除你的类作为观察者

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

其他回答

要创建自己的委托,首先需要创建一个协议并声明必要的方法,而不需要实现。然后在你的头类中实现这个协议在你想要实现委托或委托方法的地方。

协议必须声明如下:

@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声明委托(它将接收数据)。

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(这使得自动补全不那么有用),并且很难让编译器警告你打字错误和类似的错误。

让我们从一个例子开始,如果我们在网上购买一件产品,它会经过不同团队处理的运输/交付等流程。因此,如果运输完成,运输团队应该通知交付团队,并且应该是一对一的沟通,因为广播这个信息对其他人来说是一种开销/供应商可能只希望将这个信息传递给需要的人。

所以如果我们从应用的角度考虑,一个事件可以是一个在线订单,不同的团队可以是多个视图。

下面是代码,将ShippingView作为发货团队,将DeliveryView作为交付团队:

//Declare the protocol with functions having info which needs to be communicated
protocol ShippingDelegate : class {
    func productShipped(productID : String)
}
//shippingView which shows shipping status of products
class ShippingView : UIView
{

    weak var delegate:ShippingDelegate?
    var productID : String

    @IBAction func checkShippingStatus(sender: UIButton)
    {
        // if product is shipped
        delegate?.productShipped(productID: productID)
    }
}
//Delivery view which shows delivery status & tracking info
class DeliveryView: UIView,ShippingDelegate
{
    func productShipped(productID : String)
    {
        // update status on view & perform delivery
    }
}

//Main page on app which has both views & shows updated info on product whole status
class ProductViewController : UIViewController
{
    var shippingView : ShippingView
    var deliveryView : DeliveryView

    override func viewDidLoad() {
        super.viewDidLoad()
        // as we want to update shipping info on delivery view, so assign delegate to delivery object
        // whenever shipping status gets updated it will call productShipped method in DeliveryView & update UI.
        shippingView.delegate = deliveryView
        //
    }
}

这并不是问题的答案,但如果你在查找如何创建自己的委托也许一些更简单的东西会是更好的答案。

我很少实现委托,因为我很少需要。对于一个委托对象,我只能有一个委托。所以如果你想让你的委托进行单向通信/传递数据,你最好使用通知。

NSNotification可以将对象传递给多个接收者,它非常容易使用。 它是这样工作的:

MyClass。M文件应该是这样的

#import "MyClass.h"
@implementation MyClass 

- (void) myMethodToDoStuff {
//this will post a notification with myClassData (NSArray in this case)  in its userInfo dict and self as an object
[[NSNotificationCenter defaultCenter] postNotificationName:@"myClassUpdatedData"
                                                    object:self
                                                  userInfo:[NSDictionary dictionaryWithObject:selectedLocation[@"myClassData"] forKey:@"myClassData"]];
}
@end

在其他类中使用通知: 添加类作为观察者:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];

实现选择器:

- (void) otherClassUpdatedItsData:(NSNotification *)note {
    NSLog(@"*** Other class updated its data ***");
    MyClass *otherClass = [note object];  //the object itself, you can call back any selector if you want
    NSArray *otherClassData = [note userInfo][@"myClassData"]; //get myClass data object and do whatever you want with it
}

如果,不要忘记删除你的类作为观察者

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}