2
votes

Okay, so I did all the research for this issue but none of the existing solutions seem to address my problem, so here it is:

  • I have a custom class that extends UIScrollView (and contains a UIView)
  • I'd like to override the scrollViewDidScroll method from UIScrollViewDelegate (but not all the methods)

I have already tried implementing the code from this issue: How to subclass UIScrollView and make the delegate property private but for some reason, it doesn't do anything (the custom method that was overridden never gets called). I also know that you don't have to implement all the methods from UIScrollViewDelegate if you create a custom delegate class that implements the protocol (as per iPhone: Do I need to implement all methods for UIScrollViewDelegate (or any delegate)) - but when I do this:

MyScrollViewDelegate.h

@interface MyScrollViewDelegate: NSObject <UIScrollViewDelegate>

-(void)scrollViewDidScroll:(UIScrollView *)scrollView;

@end

MyScrollViewDelegate.m

@implementation MyScrollViewDelegate

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"Custom scrollViewDidScroll called.");
    // -- some more custom code here --
    // ...
}

@end

In the subclass which extends UIScrollView

// this scrollview is initiated by the NIB
- (void)awakeFromNib
{
    ...
    [self setDelegate:[[MyScrollViewDelegate alloc] init]];
}

But while it compiles and runs, when I try to scroll the scrollable view, it crashes with EXC_BAD_ACCESS and a cryptic "(lldb)" message in the debug console.

So I'm bit at a loss here what to do.

1

1 Answers

2
votes

I do have an implementation of How to subclass UIScrollView and make the delegate property private that works. My guess why your code didn't do anything: double check if you actually set the scroll view's contentSize to something bigger than your view's size. If it is smaller then there is no scrolling, just bouncing, and the scrollViewDidScroll is not called.

For you code, you actually have two issues in one line. First, the delegate property of UIScrollView is of type assign. That is if the delegate class is not retained somewhere else it will disappear in some time and you will get EXC_BAD_ACCESS. Second, by assigning [[MyScrollViewDelegate alloc] init] to the delegate and not releasing that object you create an orphan object which reference count is 1 and that will never be released. My guess is that the system recognizes the orphan object in run-time and cleans it up, after that you get your EXC_BAD_ACCESS when the delegate is sent a message.

If you prefer to use your version with separate delegate I would fix it as follows:

@interface MyScrollView: UIScrollView
{
    id<NSObject, MyScrollViewDelegate> dlgt;
    ...
}
...
@end

@implementation MyScrollView
- (void)awakeFromNib
{
    ...
    dlgt = [[MyScrollViewDelegate alloc] init];
    [self setDelegate:dlgt];
}

-dealloc
{
    [dlgt release];
    [super dealloc];
}
@end

Still, don't forget to set the contentSize to something bigger than the view bounds. Otherwise there will be no scrolling and no delegate calls.