2

I can try to explain this in terms of a UIScrollView

I'll make a subclass of UIScrollView. I want to be able to respond to its own delegate methods such as scrollViewDidScroll but at the same time let the delegate get set as normal. How can I not interfere with the delegate property, but still have the subclass be able to respond to its own delegate calls?

bneely
  • 9,083
  • 4
  • 38
  • 46
Nathan
  • 139
  • 10
  • You can add a second delegate to your custom UIScrollView, that's trigger its owns methods. – Larme Mar 06 '14 at 18:30
  • @Larme Thanks for the input, but that is not exactly what I'm asking, sorry if I'm unclear. I want the delegate class to be able to implement all the delegate methods that UIScrollViewDelegate has to offer. But I just want to also "listen in" on a select few delegate methods, I don't want to have to implement every delegate method in the subclass just so I can foreword them to its own delegate. – Nathan Mar 06 '14 at 18:36
  • possible duplicate of [How to subclass UIScrollView and make the delegate property private](http://stackoverflow.com/questions/9978279/how-to-subclass-uiscrollview-and-make-the-delegate-property-private) – rob mayoff Mar 06 '14 at 20:49

2 Answers2

3

If you only care about scrollViewDidScroll, just override layoutSubviews:

- (void)layoutSubviews {
    [super layoutSubviews];

    // your code here
}

UIScrollView sends itself layoutSubviews just before sending scrollViewDidScroll: to its delegate.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Sweet!!, I didn't think about that. This actually works for scrollViewDidScroll exactly as I needed, thanks. But It doesn't actually answer the question, so I don't think I should mark it as the answer. Sorry – Nathan Mar 06 '14 at 20:35
2

This will take some time but you can achieve what you want.

//EDITED

I have added implementation of the method forwardInvocation:. This method is invoked on object when object doesn't recognize message which was sent to it.

In our case when some of the UIScrollView delegate's methods will be called and our subclass and it doesn't implement called method, forwardInvocation will be called. This method checks whether called selector is part of the UIScrollViewDelegate protocol. If yes and if 'true' delegate of our class responds to this selector we forward invocation of called selector to our custom delegate.

That being said, using this solution you don't have to implement all methods of UIScrollViewDelegate protocol in your subclass. Execution of the methods which won;t be implemented in subclass of the ScrollView will be forwarded to 'true' delegate of our subclass.

Example:

#import <objc/runtime.h>

@protocol YourSubclassDelegate<UIScrollViewDelegate>
@end

 @interface YourSubclass ()
    @property (nonatomic, weak) id<YourSubclassDelegate> delegate;
 @end


@implementation 

//override delegate setter
- (void)setDelegate:(UIScrollViewDelegate)delegate
{
  self.customDelegate = delegate;
 [super setDelegate:self];
} 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
   //do something you want
   if ([self.customDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
      [self.customDelegate scrollViewDidScroll:self];
   }
}


- (id)forwardingTargetForSelector:(SEL)selector
{
   struct objc_method_description methodDescription = protocol_getMethodDescription(@protocol(UIScrollViewDelegate), selector, YES, YES);

   if(NULL != methodDescription.name) {
      if ([self.customDelegate respondsToSelector:selector]) {
        return self.customDelegate;
      }
   }

   return nil;
 }



@end
Rafał Augustyniak
  • 2,011
  • 19
  • 14
  • This approach is good, but you can save yourself the responds to selector work by using a new protocol that extends the UIScrollViewDelegate protocol. `customDelegate` would conform to this new protocol, and would only be set in the `setDelegate` if the object conforms to the new protocol. – Patrick Goley Mar 06 '14 at 18:57
  • yea, this was my solution, I'm glad someone else thought of it too. But I was thinking there MUST be a better way. – Nathan Mar 06 '14 at 20:33
  • I have updated my answer. Less code is needed to accomplish result you want. – Rafał Augustyniak Mar 07 '14 at 19:06