Skip to content

Instantly share code, notes, and snippets.

@TheWaWaR
Last active December 15, 2015 23:49
Show Gist options
  • Save TheWaWaR/5342697 to your computer and use it in GitHub Desktop.
Save TheWaWaR/5342697 to your computer and use it in GitHub Desktop.
iOS一个动态加载数据到UITableView的源代码例子阅读笔记。

概述

应用程序代理类设置顶层视图控制,并处理了获取RSS信息(XML格式)的连接。RSS信息获取完毕后,使用了任务队列执行xml解析操作。等解析完成后将记录数据添加到记录数组中并刷新顶层视图。 顶层视图控制器控制显示记录数据,并在渲染可见元素时(满足一定条件)下载(默认异步)相应记录中的图片,然后显示出来。

  • 语境说明
    • 应用程序代理类:LazyTableAppDelegate
    • 顶层视图控制器:RootViewController
    • 负责解析XML的类:ParseOperation
    • 负责下载图片的类:IconDownloader
    • 描述记录数据的类:AppRecord
    • RSS信息:从此处http://phobos.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/toppaidapplications/limit=75/xml获取,返回结果为XML格式

[类]的说明

AppRecord pass

纯属实体类,描述记录数据

LazyTableAppDelegate

主程序委托类
  • -- UIApplicationDelegate 中的一些方法 --

  • applicationDidFinishLaunching: 应用程序加载完后进行的处理

    1. 初始化窗口
    2. 初始化记录数组(self.appRecords)并将其设为顶层控制器的成员属性
    3. 创建加载订阅列表的连接对象(将当前类的实例设为该对象的委托)
    4. 使用NSAssert检查连接是否创建成功(因为我们常常会写出非法的URL)
    5. 在手机状态栏显示一个旋转的小圈圈告诉用户当前程序正在使用网络
  • -- 类私有方法 --

  • handleLoadedApps: 处理已加载的记录,在解析操作中处理完成时调用的回调函数中被调用

    1. 将这些记录添加到记录数组中
    2. 更新顶层视图
  • handleError: 当出现错误时进行的处理

    1. 弹出一个框框显示错误信息。
  • -- NSURLConnectionDelegate 中的一些方法 --

  • connection:didReceiveResponse: 发起的连接收到响应时进行的处理

    1. 初始化数据数组
  • connection:didReceiveData: 不断接收到数据时进行的处理

    1. 不断将接收到的数据添加到数据数组中
  • connection:didFailWithError: 连接出错时进行的处理

    1. 取消状态栏中的网络连接图标
    2. 如果是因为网络中断导致的错误则初始化一个自定义的错误对象并显示之
    3. 其它错误则直接将收到的错误信息显示出来
    4. 释放网络连接(self.appListFeedConnection)对象
  • connectionDidFinishLoading: 当一个连接成功完成时进行的处理

    1. 释放网络连接对象
    2. 取消状态栏中的网络连接图标
    3. 创建一个任务队列
    4. 创建一个解析操作对象(ParseOperation)并设置其错误处理的回调函数
    5. 将该操作对象加入到任务队列中
    6. 执行一些清理操作, 此处务必释放使用过的数据数组,因为它已经不再被主线程所使用

ParseOperation

用来解析RSS订阅列表
  • initWithData:completionHandler: 初始化成员属性

  • -- NSOperation 中的一个方法 --

  • main 执行解析任务

    1. 使用 NSXMLParser 解析下载的数据
    2. 调用 completionHandler 来对解析完成后的数据进行处理
    3. 清理成员属性 : = nil
  • -- NSXMLParserDelegate 中的一些方法 --

  • parser:didStartElement:namespaceURI:qualifiedName:attributes 当遇到头标签(start tag)时进行的处理

    1. 如果遇到的是一个实体的头标签则创建一个实体,并将当前的可用实体设置为刚创建的实体。
    2. 如果遇到预期的标签名称则将 storingCharacterData 标记设置为真。
  • parser:didEndElement:namespaceURI:qualifiedName 当遇到尾标签(end tag)时进行的处理

    1. 如果当前有 可用实体,而且开始了预期的标签则将当前可用标签的值(workingPropertyString)存储到相应的字段(AppRecord)中。
    2. 如果当前有 可用实体,如果当前的结束标签是 entry 则将该实体对象存入实体数组。
  • parser:foundCharacters 找到字符时进行的处理

    1. 如果当前字符是在预期的标签内部则将其保存到 workingPropertyString中。
  • parser:parseErrorOccurred 当遇到解析错误时进行的处理

    1. 调用设定好的错误处理的回调函数(self.errorHandler)进行处理。

IconDownloader

负责从网上下载图标
  • startDownload 做一些开始下载的初始化操作

    1. 初始化网络连接(NSURLConnection)对象,并马上发起连接请求。
    2. 设置或初始化一些成员属性
  • cancelDownload 取消下载操作

    1. 取消下载连接
    2. 释放相应的成员属性
  • -- NSURLConnectionDelegate 的一些协议方法 --

  • connection:didReceiveData: 不断接收到数据时的处理

    1. 只是将数据加到相应的数据缓冲中去
  • connection:didFailWithError: 当下载因出错而失败时的处理(只消做些清理)

    1. 清理数据缓存, = nil即可
    2. 释放下载连接, = nil即可
  • connection:DidFinishLoading: 当下载完成时的处理

    1. 使用数据缓存中的数据来初始化一个图片对象
    2. 如果下载的图片尺寸不对则进行相应的调整,并将器添加到 appRecord
    3. 做一些清理操作
    4. 让 RootViewController 更新相应行的图片

RootViewController

控制UI列表的显示
  • -- UITableViewController 中的一些方法 --

  • viewDidLoad UI 加载完成后的一些操作

    1. 单纯初始化 imageDownloadsInProgress
    2. 设置 table 中每一行的高度
  • didReceiveMemoryWarning 当内存使用过多时处理

    1. 让还在下载队列中的任务都停止下载
  • tableView:numberOfRowsInSection: 给出一个标签页显示的行数

    1. 如果没有实体则设置最小值为一个默认值
  • tableView:cellForRowAtIndexPath: 给出渲染每一行的方式。

    1. 如果还没有实体则给出一个文字为Loading的Placeholder
    2. 初始化每一个 cell
    3. 对每一个 cell 进行设置
  • -- 用来支持图标下载的方法 --

  • startIconDownload:forIndexPath: 开始下载一个图标(仅在RootViewController中使用, 渲染可见cell,拖动,滚动屏幕时被调用)

    1. 如果该任务还没开始则新建一个下载器对象,将下载器放到任务队列中,并开始下载
  • loadImagesForOnscreenRows 当屏幕滚动到可见行时图标还没加载的就加载之

    1. 先找出那些可见的行
    2. 检查每一行是否有图片
    3. 如果还没有就调用startIconDownload:forIndexPath:加载之
  • appImageDidLoad: 当 ImageDownloader 完成下载后,更新相应行的图标

    1. 找出相应的下载器
    2. 取出下载器中的图标并更新至 UI
    3. 从下载任务队列中移除该下载器
  • -- UIScrollViewDelegate 中的一些方法 --

  • scrollViewDidEndDragging:willDecelerate: 当拖拽结束时开始加载图标

    1. 检查是否还在滚动,如果没在滚动就启动图标加载任务
  • scrollViewDidEndDecelerating 滚动停下来之后就开始加载图标

    1. 直接开始加载任务

[视图文件]<*.xib>的说明

RootViewController

  • 设定文件拥有者类为 RootViewController
  • Objects分组中只包含了一个普通的 UITableView
  • 其中有两个 Outlet (RootViewController和UITableView之间的Outlet)是在设置文件拥有者类后默认建立的
    • dataSource
    • delegate

MainWindow

定义应用程序主窗口的基本框架*?*
  • 文件拥有者类为 UIApplication
  • Objects 分组中的结构如下:
    • LazyTableAppDelegate 使得默认作为LazyTableAppDelegate的代理*?*
    • UINavigationController作为LazyTableAppDelegate中的navigationController
      • UINavigationBar
      • RootViewController作为LazyTableAppDelegate中的rootViewController
        • UINavigationItem

知识点

委托关系的建立

  • 如果当前类中有需要被委托的对象,需要将该对象的委托(delegate)设为当前类的实例(self),还要在当前类中实现相应委托类的委托方法
  • 如果还要采用委托类中的一些协议,则需要在头文件中将该委托类为当前类的协议*?*

网络连接的处理方式

connection:didReceiveData: 有点麻烦,让连接对象自动处理不是更好嘛
  • 实现NSURLConnectionDelegate中相应的委托方法,主要有以下几个:
    1. connection:didReceiveData: 当接收到数据包时将它们收集起来
    2. connection:didFailWithError: 连接失败时清理数据包连接对象
    3. connectionDidFinishLoading: 连接完成后对数据进行处理,并做一些清理操作
  • 创建相应的 NSURLConnection 对象(有些初始化方法会立马发起连接请求)发起请求
  • 如果要取消相应的下载操作只消向连接对象发送cancel消息,然后做相应清理即可
  • URL连接操作是异步的

任务队列(操作队列)的工作方式

  • 创建一个任务队列(NSOperationQueue)对象
  • 创建一个操作(继承自NSOperation,实现了main方法)对象
    • 将要处理的数据传递过去 (optional)
    • 提供一个操作处理完之后的回调函数 (optional)
  • 将操作对象加入到任务队列中,该操作会立马被执行
  • 记得将不再用到的对象释放掉

视图文件和视图控制器之间的关系

使用视图文件可以让开发者更直观得了解要显示的内容
  • 视图文件描述了一部分视图信息
  • 在视图文件和视图控制器之间建立Outlet和 ownership 可以让视图控制器控制相应的视图对象

疑问

  • 如何计算不规则行的高?

  • 如何动态加载记录? DONE

     -(IBAction)addCity:(id)sender
     {
     	[ tableView beginUpdates];
     	[ dataArray addObject:@"City"];
     	NSArray *paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[dataArray count]-1 inSection:0]];
     	[[self tableView] insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationTop];
     	[tableView endUpdates];
     }

[Meta information]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment