如何优雅地解决UIScrollView使用中的bug

ScrollView的位置或者其子控件位置不正确

没有注意视图控制器的透视效果

特别是子控制器的位置不对,自己都会怀疑子控件是否加到ScrollView上面去了。

1. 一般情况下都会先打断点、NSLog输出看frame是否正确,不正确会调整它。如果发现frame完全正确,才会联想到视图控制器问题的显示自动调整,这样就离成功近了一步。
2. 如果你有成功的Demo,然后一一对应,才发现视图控制器还有个透视效果属性:automaticallyAdjustsScrollViewInsets,关闭之后一切就正常了。

总结

UIScrollView的位置或者子控件的位置不正确,首先要确定其父控制器的透视效果属性:automaticallyAdjustsScrollViewInsets。其次再去检查一下frame,这个问题就OK了。

如果在某中情况下automaticallyAdjustsScrollViewInsets属性没有设置反而显示正确,那它也会造成下面的第二个问题。

ScorllView左右上下都可以随便拖拽

1.一般会想到是否是UIScorllView的contensize的大小设置跟frame不匹配造成的。
 然后打断点,NSLog输出,看看frame和contentsize,发现没什么问题。这里你会想会不会是视图控制器自动调整了某些属性

2.想得深一点会想到UIScorllView的两个方向的bounce属性:alwaysBounceVertical,alwaysBounceHorizontal,但是我们仔细一看UIScorllView.h文件,明确提示默认就是关闭的。

3.除了第1点和第2点,还有遗漏的了种情况,也是控制器的透视效果automaticallyAdjustsScrollViewInsets造成的。

总结

在使用UIScorllView控件时

1.首先确定父控制器的透视效果automaticallyAdjustsScrollViewInsets已关闭。但是这个问题也会造成这种情况。

2.然后再UIScorllView的contensize和frame是否配置正确。

3.特别需要时配置一下属性bounces,alwaysBounceVertical,alwaysBounceHorizontal。

  就可以很好的控制UIScrollView的拖拽滚动问题了。

ScrollViewDelegate中的滑动事件重复处理

UIScrollViewDelegate的代理实现

1.Method1:offset变动的时间回调

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

2.Method2:UIScrollView拖动嘎然而止时回调。

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

设置UIScrollView的offset(Meth3)

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;

注意:Method2是拖动停止的时候回调,而且不是时时监听,而Method1是只要offset变动时就会时时回调。而只要使用Method3就会运行Method1;这样就会容易造成一种BUG:

1.当UIScrollVie拖动后对外控件A时时造成影响,会在Method1中实现影响A的代码,同时结束后会运行Method2。

2.那如果A点击后影响UIScrollView的offset,我们会在A点击的事件中使用Method3,而Method3的运行又会造成Method1方法的运行,而这种情况却不会运行Method2。

Bug出现: A点击的时候,会使用Method3,间接运行Method1,而Method1中又会运行影响A的代码。(A只是点击却最后还会影响A)。

解决方法

是在Method1中判断是否是外部事件来决定是否运行影响A的代码。那这个判断怎么处理了,这个问题在我搭建滑动切换视图控制器的框架时遇到了。费了好些时间,最后我发现UIScrollView.isDragging属性直接判断是否是拖动的回调,UIScrollView自动在设置offset的时候和拖动的时候自动更改isDragging,还是最基础的方法最靠谱。

总结

1.UIScrollView使用时特别要注意要关闭父视图控制器的透视效果属性automaticallyAdjustsScrollViewInsets。否则会造成UIScrollView本身可以任意拖拽和本身及其子控件的位置问题。

2.UIScrollView拖动时时影响外部控件的时候,在 - (void)scrollViewDidScroll:(UIScrollView *)scrollView的方法中最好使用属性isDragging判断是拖动才去实现影响外部控件的代码。避免外部控件反过来作用scrollView的offset的情况。

最后推广一下让我写这篇博客的Demo:https://github.com/MaoJianxiang/SlideSwitchController