How do I create delegates in Objective-C?

2018-12-30 23:58发布

I know how delegates work, and I know how I can use them.

But how do I create them?

19条回答
梦寄多情
2楼-- · 2018-12-31 00:38

Let's start with an example , if we buy a product online ,it goes through process like shipping/delivery handled by different teams.So if shipping gets completed ,shipping team should notify delivery team & it should be one to one communication as broadcasting this information would be overhead for other people / vendor might want to pass this information only to required people.

So if we think in terms of our app, an event can be an online order & different teams can be like multiple views.

Here is code consider ShippingView as Shipping team & DeliveryView as delivery team :

//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
        //
    }
}
查看更多
闭嘴吧你
3楼-- · 2018-12-31 00:40

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;

Method:

-(void)delegateMEthod: (ArgType) arg{
}
查看更多
查无此人
4楼-- · 2018-12-31 00:43

Ok, this is not really an answer to the question, but if you are looking up how to make your own delegate maybe something far simpler could be a better answer for you.

I hardly implement my delegates because I rarely need. I can have ONLY ONE delegate for a delegate object. So if you want your delegate for one way communication/passing data than you are much better of with notifications.

NSNotification can pass objects to more than one recipients and it is very easy to use. It works like this:

MyClass.m file should look like this

#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

To use your notification in another classes: Add class as an observer:

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

Implement the selector:

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

Don't forget to remove your class as an observer if

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
查看更多
余生无你
5楼-- · 2018-12-31 00:44

As a good practice recommended by Apple, it's good for the delegate (which is a protocol, by definition), to conform to NSObject protocol.

@protocol MyDelegate <NSObject>
    ...
@end

& to create optional methods within your delegate (i.e. methods which need not necessarily be implemented), you can use the @optional annotation like this :

@protocol MyDelegate <NSObject>
    ...
    ...
      // Declaration for Methods that 'must' be implemented'
    ...
    ...
    @optional
    ...
      // Declaration for Methods that 'need not necessarily' be implemented by the class conforming to your delegate
    ...
@end

So when using methods that you have specified as optional, you need to (in your class) check with respondsToSelector if the view (that is conforming to your delegate) has actually implemented your optional method(s) or not.

查看更多
情到深处是孤独
6楼-- · 2018-12-31 00:48

lets say you have a class that you developed and want to declare a delegate property to be able to notify it when some event happens :

@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).

you will notice also that the protocol methods passes the MyClass instance to the delegate as parameter , this is best practice in case the delegate want to call some methods on MyClass instance and also helps when the delegate declares itself as MyClassDelegate to multiple MyClass instances , like when you have multiple UITableView's instances in your ViewController and declares itself as a UITableViewDelegate to all of them.

and inside your MyClass you notify the delegate with declared events as follows :

if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
     [_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}

you first check if your delegate responds to the protocol method that you are about to call in case the delegate doesn't implement it and the app will crash then (even if the protocol method is required).

查看更多
无色无味的生活
7楼-- · 2018-12-31 00:48

To create your own delegate, first you need to create a protocol and declare the necessary methods, without implementing. And then implement this protocol into your header class where you want to implement the delegate or delegate methods.

A protocol must be declared as below:

@protocol ServiceResponceDelegate <NSObject>

- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;

@end

This is the service class where some task should be done. It shows how to define delegate and how to set the delegate. In the implementation class after the task is completed the delegate's the methods are called.

@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

This is the main view class from where the service class is called by setting the delegate to itself. And also the protocol is implemented in the header class.

@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}

- (void) go;

@end

@implementation viewController

//
//some methods
//

- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}

That's it, and by implementing delegate methods in this class, control will come back once the operation/task is done.

查看更多
登录 后发表回答