I have a UIScrollView
that I need to subclass and within the subclass I need to attach the UIScrollViewDelegate
so I can implement the viewForZoomingInScrollView
method.
Then I have a UIViewController
where I need to instantiate an object of this UIScrollView
subclass that I created, and I would also like to make the UIViewController a UIScrollViewDelegate
for this object so I can implement scrollViewDidZoom
in this UIViewController
class.
How is it possible to make one object have two delegates? (I know I could easily just have one delegate and just implement both methods there, but for design purposes I'd like to do it the way that I'm mentioning).
The delegate pattern is about a 1 to 1 relationship between a class and it's delegate. Whilst it is possible to achieve some level of multiple delegation through switching the delegates in and out, it's more likely to lead to unpredictable behaviour and bugs.
Multicast Delegate is a generic wrapper around yet another delegate protocol, that means it create one-to-many delegate relationships. This allows providing an object with an array of delegates.
Delegates allow methods to be passed as parameters. Delegates can be used to define callback methods. Delegates can be chained together; for example, multiple methods can be called on a single event. Methods don't have to match the delegate type exactly.
A delegate is an object which refers to a method or you can say it is a reference type variable that can hold a reference to the methods. Delegates in C# are similar to the function pointer in C/C++. It provides a way which tells which method is to be called when an event is triggered.
Sometimes it makes sense to attach several delegates to a scroll view. In that case you can build a simple delegation splitter:
// Public interface
@interface CCDelegateSplitter : NSObject
- (void) addDelegate: (id) delegate;
- (void) addDelegates: (NSArray*) delegates;
@end
// Private interface
@interface CCDelegateSplitter ()
@property(strong) NSMutableSet *delegates;
@end
@implementation CCDelegateSplitter
- (id) init
{
self = [super init];
_delegates = [NSMutableSet set];
return self;
}
- (void) addDelegate: (id) delegate
{
[_delegates addObject:delegate];
}
- (void) addDelegates: (NSArray*) delegates
{
[_delegates addObjectsFromArray:delegates];
}
- (void) forwardInvocation: (NSInvocation*) invocation
{
for (id delegate in _delegates) {
[invocation invokeWithTarget:delegate];
}
}
- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector
{
NSMethodSignature *our = [super methodSignatureForSelector:selector];
NSMethodSignature *delegated = [(NSObject *)[_delegates anyObject] methodSignatureForSelector:selector];
return our ? our : delegated;
}
- (BOOL) respondsToSelector: (SEL) selector
{
return [[_delegates anyObject] respondsToSelector:selector];
}
@end
Then simply set an instance of this splitter as a delegate of the scroll view and attach any number of delegates to the splitter. All of them will receive the delegation events. Some caveats apply, for example all the delegates are assumed to be of the same type, otherwise you’ll have trouble with the naive respondsToSelector
implementation. This is not a big problem, it’s easy to change the implementation to only send delegation events to those who support them.
You don't want an object with 2 delegates. You want to keep your customScrollView keep the responsibility of its own UIScrollViewDelegate functions.
To make your parentVC respond to the delegate methods of UIScrollView as well you will have to make a custom delegate inside your customScrollView.
At the moment a UIScrollViewDelegate function gets called you will also call one of your delegate functions from your custom delegate. This way your parentVC will respond at the moment you want it to.
It will look somewhat like this.
CustomScrollView.h
@protocol CustomDelegate <NSObject>
//custom delegate methods
-(void)myCustomDelegateMethod;
@end
@interface CustomScrollView : UIScrollView <UIScrollViewDelegate>
{
id<CustomDelegate> delegate
//the rest of the stuff
CustomScrollView.m
-(void) viewForZoomingInScrollView
{
[self.delegate myCustomDelegateMethod];
//rest of viewForZoomingInScrollView code
ParentVC.h
@interface CustomScrollView : UIViewController <CustomDelegate>
{
//stuff
ParentVC.m
-(void)makeCustomScrollView
{
CustomScrollView *csv = [[CustomScrollView alloc] init];
csv.delegate = self;
//other stuff
}
-(void)myCustomDelegateMethod
{
//respond to viewForZoomingInScrollView
}
I hope this fully covers your problem. Good luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With