Can't zoom in/out scrollView of a class which

2019-07-26 20:29发布

问题:

I have a class which is a subclass of webView. I need to do some calculations when scrollview of webView gets zoomed or gets scrolled. The content loaded in webView are pdf files. In iOS 5 I am getting scrollView with:

[super scrollView]

and in iOS 4:

for (id subview in webView.subviews)
  if ([[subview class] isSubclassOfClass: [UIScrollView class]])
    return subview;

It's working fine with iOS 5 but in iOS 4 when I change the delegate of scrollView I can no longer zoom in/out the webView.

Any thoughts how can I change the delegate of that scrollView?

回答1:

I implemented something like this:

@interface ProxyScrollView : NSObject <UIScrollViewDelegate>
{
    UIScrollView* _view;
    id<UIScrollViewDelegate> origDelegate;
    id<UIScrollViewDelegate> newDelegate;
}

+ (ProxyScrollView*) proxyScrollViewWithScrollView: (UIScrollView*) scrollView;

@end

@implementation ProxyScrollView

- (id) initWithScrollView: (UIScrollView*) scrollView
{
    if(self != nil)
    {
        _view = scrollView;
        origDelegate = _view.delegate;
        [_view setDelegate:self];
        newDelegate = nil;
        [_view retain];

        return self;
    }

    return nil;
}

-(void)dealloc
{
    _view.delegate = origDelegate;
    [_view release];
    _view = nil;
    origDelegate = nil;
    newDelegate = nil;
}

+ (ProxyScrollView*) proxyScrollViewWithScrollView: (UIScrollView*) scrollView
{
    ProxyScrollView* retVal = [[[ProxyScrollView alloc] initWithScrollView:scrollView] autorelease];

    return retVal;
}

- (BOOL)isKindOfClass:(Class)aClass
{
    return [_view isKindOfClass:aClass];
}

- (BOOL)isMemberOfClass:(Class)aClass
{
    return [_view isMemberOfClass:aClass];
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if ( [super respondsToSelector:aSelector] )
        return YES;
    else {
        /* Here, test whether the aSelector message can     *
         * be forwarded to another object and whether that  *
         * object can respond to it. Return YES if it can.  */
        if([_view respondsToSelector:aSelector])
            return YES;
    }
    return NO;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSMethodSignature *sig = [super methodSignatureForSelector:sel];

    if(!sig)
    {
        sig = [_view methodSignatureForSelector:sel];
    }

    return sig;
}

- (void)forwardInvocation:(NSInvocation *)inv
{
    NSLog(@"inv.selector: %@", NSStringFromSelector(inv.selector));

    if([_view respondsToSelector: inv.selector])
    {
        [inv invokeWithTarget: _view];
    }
}

- (void)setDelegate:(id<UIScrollViewDelegate>)delegate
{
    newDelegate = delegate; 
}


- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView 
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
    if([origDelegate respondsToSelector:_cmd])
        return [origDelegate performSelector:_cmd withObject:scrollView];

    return nil;
}

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_2)
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView withObject:view];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView withObject:view];
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate scrollViewDidEndZooming:scrollView withView:view atScale:scale];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate scrollViewDidEndZooming:scrollView withView:view atScale:scale];
}

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate scrollViewShouldScrollToTop:scrollView];
    if([origDelegate respondsToSelector:_cmd])
        return [origDelegate scrollViewShouldScrollToTop:scrollView];

    return false;
}

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
{
    if([origDelegate respondsToSelector:_cmd])
        [origDelegate performSelector:_cmd withObject:scrollView];
    if([newDelegate respondsToSelector:_cmd])
        [newDelegate performSelector:_cmd withObject:scrollView];
}

@end

Then I return:

for (id subview in webView.subviews)
  if ([[subview class] isSubclassOfClass: [UIScrollView class]])
    return [ProxyScrollView proxyScrollViewWithScrollView: (UIScrollView*) subview];

In my case, I keep a singleton ProxyScrollView for my webView and return that.