Extend with Delegates

 // Introduction

We've all used delegates in the Cocoa frameworks. Classes like NSTableView and NSToolbar use them to provide the data they display and to extend their functionality. Today we'll talk about implementing delegates in our own classes. It's a relatively simple thing to do, but there are a couple gotchas that you have to watch out for.

 


 

// Interface

The first step in creating a delegate is adding the needed support structure to the class's interface. An instance variable that will hold the reference to the class we will delegate to is added along with the prototypes for its accessor methods. The type of the variable is id since the object can be any class that wishes to conform to the delegate.

 

#import <Foundation/Foundation.h>

@interface CDCOurClass : NSObject
{
    ...
	
    id _delegate;
    
    ...
}

...

- (id)delegate;
- (void)setDelegate:(id)new_delegate;
@end

 

The other item we have to add to the header file is the interface for the delegate methods. It is an informal protocol that is declared as a category of the NSObject class. NSObject is used because every class inherits from it and can therefore implement the methods.

 

@interface NSObject (CDCOurClassDelegate)

- (void)ourDelegate;
- (id)anotherDelegate:(id)p1 withParam:(id)p2;

@end

 

 


 

// Implementation

The accessor methods are implemented in a manner similar to any other set of accessors. There is one very important difference. The delegate class is not retained. If it was retained, a circular reference would be created since CDCOurClass is an object in the delegate class. This fact is also the reason that it is safe not to retain. The purpose of retaining is to keep the object from being deallocated while it is still being used. Since the instance of CDCOurClass resides inside the delegate, the CDCOurClass instance will be destroyed before the delegate is deallocated.

 

- (id)delegate
{
    return _delegate;
}

- (void)setDelegate:(id)new_delegate
{
    _delegate = new_delegate;
}

@end

 

The delegate is all set to go now. To invoke one of the delegate methods, it gets called like any other method. The delegate class may no implement the delegate though. It should be checked first to make sure it responds to the method call. The check can also be cached in the set accessor to improve efficency and performance.

 

- (id)someMethodInCDCOurClass
{
    ...
	
    if ([_delegate respondsToSelector:@selector(ourDelegate)])
        [_delegate ourDelegate];
    else
    { 
        [NSException raise:NSInternalInconsistencyException
            format:@"Delegate doesn't respond to ourDelegate"];
    }
    
    ...
}

 

 


 

// Notify

The standard behavior of a Cocoa class is that the delegate class is automatically registered for any notifications that the delegator posts. This etiquette should be extended if your class posts any notifications. In the "setter" accessor, each notification that the delegate class responds to gets added to the notification center as an observer.

 

- (void)setDelegate:(id)new_delegate
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
	
    if (_delegate)
        [nc removeObserver:_delegate name:nil object:self];
		
    _delegate = new_delegate;
    
    // repeat  the following for each notification
    if ([_delegate respondsToSelector:@selector(ourNotifName:)])
        [nc addObserver:_delegate selector:@selector(ourNotifName:)
            name:CDCOurClassourNotifNameNotification object:self];
}

 

The last thing left to do is to unregister the delegate when the class gets deallocated.

 

- (void)dealloc
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
	
    if (_delegate)
        [nc removeObserver:_delegate name:nil object:self];
		
    [super dealloc];
}

 

 


 

// Conclusion

That pretty much covers how to add a delegate. The key points to remember are: do not retain the delegate, register the delegate for any notifications, and check that the delegate responds to a method before calling it. Have fun with them.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值