美文网首页小知识点ios实用开发技巧iOS知识收集
iOS:如何复用两个view实现可无限滚动的全屏页面

iOS:如何复用两个view实现可无限滚动的全屏页面

作者: redihd | 来源:发表于2015-08-17 17:49 被阅读3422次

    学iOS的应该没有没用过tableView的吧,tableView里面会对dequeueReusableCellWithIdentifier申明的cell根据identifier进行复用,而cell的复用相信会让一些初学者有一些困扰,它是怎么实现复用的,为什么我这么写,cell会变得好乱,完全不是我想要的。
    而在平常的需求里面也会遇到一些需要横向的可循环使用的视图的需求
    如下图,

    headTabbarWithViews.gif
    如果每需要一个就重新创建一个view的话,这么多view会占用太多的内存了,而且其实很多view,完全是占着茅坑不拉屎。所以,我们一般都会用复用其中的view,如果我们实现了这样一个有复用视图,对于以后多个imageViewtableView等就有一个比较好的处理方法了

    以上就是我写这个pageListView的原因, 1.增强对于复用的理解 2.便于平常项目里面对于一些可重复使用的view做一个简单地集成封装。

    其实我们要实现的pageListView复用的原理和tableView对于cell的复用的原理基本一致,只是简单了很多。因为我们目前考虑的都是一页一页的切换。所以不必考虑这个viewsize和滑动完之后停留在两个view中间的情况。

    简单说一下我们目前的思路,其实和tableViewCell复用的机制类似,创建两个池子,一个放可视区域的views,另一个放可复用views。当需要展示一个view,而复用池为空时,就创建一个新的view,并将这个view放在可视views池,如果一个view已经完全出了可视区域,就把它放入复用池,每次加载view的时候给view设置一下frame
    上面讲了最基本的思路,下面让我们来实现看看。

    https://github.com/redihd/PageListView
    这个是我实现一个可复用的pageListView的代码,想看的可以拉下来看一下。
    下面我会用我实现的代码来做简单的讲解。

    pageView.h

    因为要实现的view很简单,所以我们在.h文件中也没有太多的属性与方法,主要就是有个三个block来实现类似tableViewdatasourcedelegate。其中loadViewAtIndexBlock 需要两个传入参数,会有一个返回的view,这个block实现了类似- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;这个方法。在接下来我们会细讲这个block的功能。
    再来看.m文件里面的属性

    pageview.m头
    我们将一些不需要对外暴露的都放在了.m中,其中两个属性visibleListViewsItems,dequeueViewPool是实现能够复用viewpageView的关键。
    visibleListViewsItems :这个可变字典用来存储可视区域的视图及其对应的index。
    dequeueViewPool:这个可变set用来存储可复用的视图。
    .m文件中大多数方法都是设置frame,位移等,我们这里不谈,主要介绍其中几个关键方法 loadDequeueViewAndVisibleViewsIfNeeded.png

    loadDequeueViewAndVisibleViewsIfNeeded该方法主要是在scrollview的contentOffset.x变化时,计算应该要在可视视图字典中的视图,把旧的可视视图字典里面的视图移动到可重用视图池,然后将要新的展示的视图取出来,加入可视视图字典。

    loadViewAtIndex
    loadViewAtIndex该方法主要是从我们datasourceblock获取要展示的view,这个view默认是从复用池即visibleListViewsItems任意取一个view来当做我们将要展示的view,并将其与index加入visibleListViewsItems,如果block提供的view为空,再新建一个view。然后将原来在view要展示的位置的视图(如果还有的话)移除,并加入visibleListViewsItems

    基本思路就是这样了

    然后关于如何使用这个view

    initPageView.png

    totalPagesCountBlock 这个block设置有多少个view要展示
    loadViewAtIndexBlock 这个block处理可重用的视图
    pageViewClickBlock 这个block处理点击事件
    个人比较喜欢用block,所以把delegate和datasource都用block来做了。

    最后跑一下,可以看到,即使设置了60000个,但是cpu和memory都还是很小。


    run

    最后,其实我们现在要实现这种视图,用横向的collectionView来做就好了。但是,写一个这种对于个人理解一些东西的实现还是有帮助的。接下来可能会把这个写的更详细,功能再多一些。
    另外再就是自己用uiview实现一个缺一部分功能的scrollView。

    相关文章

      网友评论

      • X__Z:大神 你好 请问一下,如果要实现view可横向纵向都复用,就是scrollview可上下左右滚动,该怎样实现呢?十分感谢
      • hhgvg:楼主大神 帮个忙呀 有很多个tableview 我要他复用
        hhgvg:@redihd 只有一个Tableview 我要在tableview上执行动作事件
        redihd:你把tableview 换成我demo里的uilabel 然后绑定对应的数据源 刷新即可
      • hhgvg:是用两个view复用?
        redihd:这个你自己先考虑和研究一下吧 不难
        hhgvg:@redihd 我看了 确实可以 楼主 我现在要将tableview替换UILabel 加载上面 每次滑动的时候重新加载数据。。 该怎么实现呢
        redihd:是的,因为在屏幕范围内最多只显示两个页面(滑动到一半的时候显示两个,停下来只显示一个)
        所以两个就够,可以看我代码
        https://github.com/redihd/PageListView
      • 不必luo嗦:请问一下复用池除了用nsset来做,还可以用什么来充当。最好应该用什么来充当复用池,谢谢
      • 白云之巅1992:不是太理解,如果每个view上放的东西不一样(比较第一个view有轮播图其他view有的是瀑布流有的是一个列表),每个view都还能做复用么?
        redihd:@CoderZXY 你说的这个就类似 tableview的cell 有几种类型 你可以创建 几种cell 这样每种cell只负责他们那种cell的复用,你也可以 全部放在一个cell上(根据类型判断是不是显示,不过不推荐这样做)这样全部cell都是一个复用池 来管理了
        简单的说复用是由复用池 来管理的 cell的这个 dequeueReusableCellWithIdentifier: Identifier这个就是每个复用池的唯一标识,你可以这么理解
      • OCDak:你好,我在使用这个Demo的时候往,发现label.text的赋值会走两次,这就导致如果赋值自定义数组的时候会出现数组越界的情况。而且当往每个dequeueView添加自定义的View的时候发现复用出现问题,本人技术渣,还望博主不吝赐教~
        OCDak:好的~谢谢
        redihd:@OCDak 因为这个demo会在你往左滑的时候加载下一个view,这个demo大概就是讲一下思路。
        需要比较完整且没有什么问题的demo可以看我下一篇文章http://www.jianshu.com/p/0e90c20c4a39
      • Alice_Ace:你好,你说可以用横向的collectionView的做,那用tableview可以的东西,没必要用collectionView的,你认为哪种方式性能更好呢?
        Alice_Ace:@redihd 我发现60000在tablebview上内存100多M,用你的demo试了一下20多M :smile:
        redihd:@Alice_Ace 如果你只是做列表的需求,那么其实两者的性能是没有区别的,都实现了对cell和view(tableView的header,footer,collectionView的 Supplementary view等)的复用,而且大多数人应该都习惯于用tableView 所以就用tableView 但是如果要实现复杂一些的视图效果,比如 瀑布流、多列或者更复杂的,推荐使用collectionView。
      • oriyum:感觉好牛逼,但是看不懂
        oriyum:@redihd 好的,谢谢。
        redihd:@飘扬过海 可以去git上下demo配合着看
      • 叶舞清风:不错的想法

      本文标题:iOS:如何复用两个view实现可无限滚动的全屏页面

      本文链接:https://www.haomeiwen.com/subject/jcnwqttx.html