转载请保留地址wossoneri.com

问题

首先看一下我之前写的demo:link

demo是封装了一个控件,直接在MainViewControllerviewWillAppear里初始化,并且调用一个初始化滚动到中间的方法,方法主要是调用了

- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;

方法,在初始化后将其滚动到中间的区域。不过,当我在项目里使用的时候,遇到了调用该方法却无法滚动到中间的情况。

我的使用步骤是:在我界面的UIView中,创建该控件对象并且调用滚动到中间的方法。

scrollToItemAtIndexPath使用

发现效果无法实现,我第一时间检查了函数有没有调用,然后发现是调用的了,但没有出现该出现的效果。所以简单看一下该方法的官方注释。xcode提示的描述是:

Scrolls the collection view contents until the specified item is visible.只是方法的作用,并没有说使用条件。为了快速解决问题,google了一下scrolltoitematindexpath not working,在这里:link找到了答案:

不知道这是一个bug还是一个特性,每当在UICollectionView显示它的subview之前调用scrollToItemAtIndexPath:atScrollPosition:Animated方法,UIKit就会报错。

所以要解决它,就应该在viewController中,在你能确认CollectionView完全计算出其subview布局的地方去调用这个方法。比如在viewDidLayoutSubviews里调用就没有问题。

方法的意思已经明确,就是找到一个能计算出collectionview的所有布局地方调用滚动方法。但我的界面使用的是自动布局,只在模块外有一个viewController,其余的都是在UIView中创建添加,所以在我使用这个控件对象的地方,我无法复写viewController的方法。所以想了几个办法。

-layoutsubviews

既然情况发生在UIView中,那首先想到的是重写该方法。重写之前,看一下文档说明:

Lays out subviews.

Discussion

The default implementation of this method does nothing on iOS 5.1 and earlier. Otherwise, the default implementation uses any constraints you have set to determine the size and position of any subviews.

Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.

You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.

该方法为子view布局。

子类可以复写该方法为子view实现更精确的布局。但你只应该在用自动布局时无法实现效果时用它。而且你不应该直接调用该方法,如果需要强制刷新布局,调用setNeedLayout,会在下一次绘制刷新前更新布局。调用layoutIfNeed可以立即刷新布局。

看起来这个方法有用,我便试了一下。

[self setNeedLayout];
[self layoutIfNeed];
[myPicker scrollToCenter];

然而还是没有效果。

view.window

前面的方法没效果,我又想了一下scrolltoitematindexpath的实现条件,是在UICollectionView显示之后调用才有效,所以我需要在UIView中获得它显示的状态再去滚动。幸好,我的控件也是继承UIView的,其中有这么一个属性:

Property: window

This property is nil if the view has not yet been added to a window.

也就是说这个属性值代表着这个view有没有放在窗口中显示,那么我就需要在当前UIView的生命周期中检查myPicker对象的这个属性就好了。所以最后的解决方法是,起一个子线程,对myPicker的状态进行检查,当状态为显示的时候调用滚动方法:

NSThread *checkShownThread;
checkShownThread = [[NSThread alloc] initWithTarget:self selector:@selector(checkIfViewIsShowing) object:nil];
[checkShownThread start]; - (void)checkIfViewIsShowing {
while (1) {
if (hPicker.window != nil) {
break;
}
} dispatch_async(dispatch_get_main_queue(), ^{
[hPicker scrollToCenter];
}); [checkShownThread cancel];
checkShownThread = nil;
}

小结

这个bug只是一个很小的bug,我记录它的原因,一方面是解决过程中学习到了一些不了解的方法,另一方面是记录一下解决问题的思路,希望可以对以后的学习有帮助。也希望将来回头看这一段的时候可以对问题有更好的解决思路。

[iOS] UICollectionView初始化滚动到中间的bug的更多相关文章

  1. iOS UICollectionView 在滚动时停在某个item位置上

    方法一:实现UIScrollView的代理,然后实现下面这个方法 #pragma mark - UIScrollViewDelegate//预计出大概位置,经过精确定位获得准备位置- (void)sc ...

  2. [iOS] UICollectionView实现图片水平滚动

    最新更新: 简单封装了一下代码,参考新文章:UICollectionView实现图片水平滚动 先简单看一下效果: 新博客:http://wossoneri.github.io 准备数据 首先先加入一些 ...

  3. iOS无限循环滚动scrollview

    经常有园友会问"博主,有没有图片无限滚动的Demo呀?", 正儿八经的图片滚动的Demo我这儿还真没有,今天呢就封装一个可以在项目中直接使用的图片轮播.没看过其他iOS图片无限轮播 ...

  4. iOS关于菜单滚动视图实现

    菜单滚动视图也是在项目开发过程中比较常用到的功能,先直接看效果图 实现的效果如下: 当菜单个数的总长度超过一个屏宽度就计算每一个的文字宽度,若没有则只进行一个屏平分,点击菜单项时,滚动的视图位置会随着 ...

  5. Android RecyclerView 滚动到中间位置

    最近看到QQ音乐的歌词每次滑动后都可以滚回到中间位置.觉得甚是神奇,打开开发者模式显示布局,发现歌词部分不是采用 android 控件的写的,应该是前端写的.于是,我想,能不能用 recyclerVi ...

  6. UITableViewCell上放UICollectionView ,UICollectionViewCell无法复用bug

    如题: UITableViewCell上放UICollectionView ,UICollectionViewCell无法复用bug 如果UITableViewCell的size大于整个collect ...

  7. 处理ios的overflow滚动bug

    先说说这个bug的场景 .container{ height:100vh; overflow-y:scroll; } 没毛病,总有这种类似的情况,需要在容器内滚动,但是!这种容器内的滚动在ios上面处 ...

  8. iOS UICollectionView之二(垂直滚动)

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

  9. iOS UICollectionView之-(水平滚动)

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

随机推荐

  1. android初探

    随着nodejs的不断发展,前端的范围越来越大,所以,适当的了解移动端是非常有必要的,比如使用RN开发app,前端必须要和安卓工程师沟通共同开发,那么学习android的基本知识就很重要了,因为目前安 ...

  2. i=i+1,i+=1,i++哪个执行效率最高?为什么?

    (1)i=i+1最低,它的执行过程如下:读取右i的地址i+1读取左i的地址将右值传给左边的i(编译器并不认为左右i的地址相同)(2)i+=1其次,它的执行过程如下:读取左x的地址i+1将得到的值传给i ...

  3. nodejs结合apiblue实现MockServer

    apiblue功能很强大,里面支持很多插件,这些插件能够为restfulAPI提供接口文档自动生成,甚至Mockserver的功能,当然,好多插件还是有很多坑的.下面用apiblue实现下面的业务需求 ...

  4. 使用Codis-Admin命令配置环境

    前提条件:由于22.35.60服务器各自配置了Codis-Service主机,所以22.35.60对应的ip和端口要求能通信和互信访问,为下面通过60的dashboard配置22.35.60实现分组. ...

  5. Java实现排行榜基于Redis

    访问我的博客 前言 排行榜作为互联网应用中几乎必不可少的一个元素,其能够勾起人类自身对比的欲望,从而来增加商品的销量.排行榜的实现方式基本大同小异,大部分都基于 Redis 的有序集合 sorted ...

  6. WPF中一个控件绑定另一个控件的属性

    如同一个Grid中的一个按钮根据另一个按钮的显示与否作出不同的响应: 绑定的时候通过ElementName来指定控件 <Grid Margin="50,130"> &l ...

  7. Netty 接受请求过程源码分析 (基于4.1.23)

    前言 在前文中,我们分析了服务器是如何启动的.而服务器启动后肯定是要接受客户端请求并返回客户端想要的信息的,否则要你服务器干啥子呢?所以,我们今天就分析分析 Netty 在启动之后是如何接受客户端请求 ...

  8. Mac Hadoop的安装与配置

    这里介绍Hadoop在mac下的安装与配置. 安装及配置Hadoop 首先安装Hadoop $ brew install Hadoop 配置ssh免密码登录 用dsa密钥认证来生成一对公钥和私钥: $ ...

  9. 微信小程序开发资料汇总

    >> 微信小程序开发工具下载 社区推荐: >>蜂鸟-微信小程序开发者社区>> 很快-微信小程序开发者社区 博文推荐: >> 微信小程序开源Demo精选& ...

  10. 【Java基础】7、Java同步机制之Monitor监视器与syncrhoized实现原理

    一:Monitor Monitor是一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量. 它内置与每一个Object对象中,相当于一个许可证.拿到许可证即可以进行操作,没有拿到则需 ...