UIWebView scrollView 没有在触摸时调用 scrollViewDidScroll

Posted

技术标签:

【中文标题】UIWebView scrollView 没有在触摸时调用 scrollViewDidScroll【英文标题】:UIWebView scrollView not calling scrollViewDidScroll on touch 【发布时间】:2013-06-22 17:20:15 【问题描述】:

我正在为 ios 6 进行开发,我正在开发一种位于 UIWebView 顶部的工具栏,当您在 UIWebView 上向上滚动时,该工具栏会后退。

我的想法是,我可以设置 UIWebView 内的 UIScrollView 的委托来向我的 UIViewController 发送消息,这将动画顶部工具栏上的约束以使其缩小和移动等等。

但是,scrollViewDidScroll: 方法似乎没有被调用,这让我很困惑。

现在,SO 上还有许多与此类似的其他问题,其中大部分似乎是人们忘记在 scrollView 上设置委托属性...

Why does a UIWebView instance not call scrollViewDidScroll? - 代表。 scrollViewDidScroll never called - 代表。 UIWebView not calling UIScrollViewDelegate methods - 代表?不得不说。 How to implement scrollViewDidScroll in UIScrollView - 代表。 scrollViewDidScroll not executing - 和...代表。

不用说,我正在设置委托。部分代码sn-ps:

SDDefinitionViewController.h:

@interface SDDefinitionViewController : UIViewController <UIWebViewDelegate, UIScrollViewDelegate>
...

SDDefinitionViewController.m:

...
- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self loadDefinitions];

    // Grab a reference to the ScrollView so that we can set the delegate and then use those method calls to animate the top bar.
    self.scrollView = self.webView.scrollView;
    self.scrollView.delegate = self;
    self.lastScrollViewVerticalOffset = 0;

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

    // (Code) <= Never gets called

...

而且,最重要的是,我做了一些调试器控制台操作:

(lldb) po self
$0 = 0x095c0600 <SDDefinitionViewController: 0x95c0600>
(lldb) po self.scrollView
$1 = 0x0954e8d0 <_UIWebViewScrollView: 0x954e8d0; frame = (0 0; 1024 596); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x954ec50>; layer = <CALayer: 0x954eab0>; contentOffset: 0, 0>
(lldb) po self.scrollView.delegate
$2 = 0x095c0600 <SDDefinitionViewController: 0x95c0600>

所以,delegate 的设置肯定是正确的,不会随机释放任何东西。

最后,我以编程方式在self.scrollView 上调用了setContentOffset,并且委托方法确实 被调用了。但这并没有真正的帮助,因为我想检测用户何时使用手势滚动。

那么,这有什么独家新闻呢?为什么 scrollView 不会调用它的委托方法?

编辑:

因此,使用Reveal 查看我的应用程序,我发现我的 UIWebView 有一个 _UIWebViewScrollView 作为子视图,并且在其下方有一个 UIWebBrowserView。 UIWebBrowserView 的大小与 UIWebView 完全相同...

可能是 UIWebViewScrollView 没有正常的内容视图,它会偏移等等,webkit 正在滚动还是什么?

【问题讨论】:

【参考方案1】:

作为UIWebView 内部实现UIScrollViewDelegate 方法。 UIScrollViewDelegate 不太可能被重新分配给除当前 UIWebView 对象之外的其他对象。 所以,我找到了一个小工作。您可以继承 UIWebView 实现该类中的UIScrollViewDelegate 方法,并且不要忘记将该方法转发给超级,否则可能会发生意外行为。

这就是我解决上述问题的方法:

/////in WebView.h file
//////WebView is subclass of UIWebView
#import <UIKit/UIKit.h>

@interface WebView : UIWebView
 @property(nonatomic,weak) NSObject <UIScrollViewDelegate> *mScrollDelegate;
@end

//// in WebView.m file
#import "WebView.h"
@synthesize mScrollDelegate;
@implementation WebView

- (id)init

    self = [super init];
    if (self) 
        self.scrollView.delegate = self;
    
    return self;


/////scrollViewDidScroll Method, Also I am forwarding it to super class UIWebView
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
    [super scrollViewDidScroll:scrollView];
    if([self.mScrollDelegate respondsToSelector:@selector(scrollViewDidScroll:)])
         [self.mScrollDelegate scrollViewDidScroll:scrollView];
    
    NSLog(@"scrollViewDidScroll");


@end

并确保您的self.webView 必须是WebView 类型。 在 SDDefinitionViewController.m

self.webView.mScrollDelegate = self;

现在 SDDefinitionViewController.m 中的 scrollViewDidScroll 方法将被调用

【讨论】:

感谢您的回复。问题:在我上面的帖子中,当我在self.webView.scrollView 上直接调用setContentOffset: 时,它确实 在我的视图控制器上调用了scrollViewDidScroll:,这表明我已经成功地将滚动视图的委托设置为我的视图控制器。你确定子类化UIWebView 是必要的吗?我相信问题在于滚动视图根本没有调用scrollViewDidScroll:,无论代表是谁......除非你有更多信息? 考虑在子 scrollViewcontentOffset 属性上使用 KVO。修改 UIScrollView 的委托属性不一定是安全的,因为 UIWebView 可以在内部使用它。【参考方案2】:

我会回答我自己的问题,即使答案很愚蠢。

与我一起从事该项目的另一个人设置了 UIWebView 的内容,发现 Web 视图中的滚动视图没有正确滚动。所以他禁用了 web 视图的滚动,然后在 html 中粘贴了-webkit-overflow-scrolling: touch; 标签,这导致 webkit 滚动而不是 web 视图——尽管它看起来大致相同。他试图解决的最初问题是,某些 div,无论出于何种原因,具有 CSS 样式 overflow:hidden;,这导致 div 的实际大小不适合其内容,并使 web 视图认为页面非常小,因此滚动不起作用。

这花了我大约 8 个小时来解决,尽管我承认当我缺乏 Web 开发知识导致我从字面上破解 CSS 样式表直到我弄清楚是什么属性导致 div 不自动-size 到他们的内容。

无论如何,也许有一天这会对某人有所帮助。

【讨论】:

以上是关于UIWebView scrollView 没有在触摸时调用 scrollViewDidScroll的主要内容,如果未能解决你的问题,请参考以下文章

在目标 c 中从 UIWebView.scrollView 写入 PDF 文件

UIScrollview中的UIWebview向scrollview发送垂直滚动事件

在缩放时,使用UIWebView scrollView更新UITableViewCell中的约束无法正常工作

出现在UIWebView底部的黑线。怎么删除?

将一页 UIScrollView 保存到图像

webview加载网页获取高度