在这里,你将会学习到解析JSON数据,网络请求功能,动态调整cell内容等功能!!!

最终的结果 是这样的,项目相对简单,很适合入门!下面让我们一起开始教程之旅吧!

1、先看下项目工程结构:

第一步:创建Utitlities文件夹,先完成基础通用的辅助功能

1、网络请求类:HttpRequest.swift

[objc] view plaincopyprint?
  1. import Foundation
  2. ///
  3. /// @brief 网络请求相关类
  4. /// @date  2014-10-09
  5. /// @author huangyibiao
  6. ///
  7. class HttpRequest: NSObject {
  8. override init() {
  9. super.init()
  10. }
  11. ///
  12. /// @brief 把二进制数据转换成JSON格式的数据
  13. /// @param data NSDictionary?类型,网络请求返回来的二进制数据
  14. /// @return 如果解析成功,返回NSDictionary?类型的JSON数据;如果解析失败,会返回nil
  15. ///
  16. class func parseJSONData(data: AnyObject?) ->NSDictionary? {
  17. if let downloadData: NSData = data as? NSData {
  18. var jsonData: AnyObject? = NSJSONSerialization.JSONObjectWithData(downloadData,
  19. options: NSJSONReadingOptions.MutableContainers,
  20. error: nil) as? NSDictionary
  21. return jsonData as? NSDictionary
  22. }
  23. // 当解析失败时,会返回nil
  24. return nil
  25. }
  26. ///
  27. /// @brief 异步网络请求方法,需要请求地址参数及回调
  28. /// @param urlString 请求地址
  29. /// @param completion 请求完成或者请求失败的回调
  30. /// @return 请求成功时,会返回NSDictionary?的字典格式的数据,如果请求失败,会返回nil
  31. ///
  32. class func request(#urlString: String?, completion: (data: NSDictionary?) ->Void) {
  33. if urlString == nil {
  34. dispatch_async(dispatch_get_main_queue(), { () -> Void in
  35. println("urlstring 为空")
  36. // 请求出现,则返回nil对象表示
  37. completion(data: nil)
  38. })
  39. return
  40. }
  41. let url = NSURL.URLWithString(urlString!)
  42. let request = NSURLRequest(URL: url)
  43. let queue = NSOperationQueue()
  44. NSURLConnection.sendAsynchronousRequest(request, queue: queue) {
  45. (response, data, error) -> Void in
  46. if error != nil {
  47. dispatch_async(dispatch_get_main_queue(), { () -> Void in
  48. println(error)
  49. // 请求出现,则返回nil对象表示
  50. completion(data: nil)
  51. })
  52. } else { // 请求成功,则返回正确的数据
  53. let parseData = self.parseJSONData(data)
  54. dispatch_async(dispatch_get_main_queue(), { () -> Void in
  55. completion(data: parseData)
  56. })
  57. }
  58. }
  59. }
  60. }

2、对String的扩展:

[objc] view plaincopyprint?
  1. import Foundation
  2. import UIKit
  3. ///
  4. /// @brief String的通用扩展方法
  5. /// @date  2014-10-09
  6. /// @author huangyibiao
  7. ///
  8. extension String {
  9. ///
  10. /// @brief 获取字符串的高度
  11. /// @param fontSize 字体大小
  12. /// @param width 限制一行显示的宽度
  13. /// @return 返回文本在width宽度的条件下的总高度
  14. ///
  15. func height(let fontSize: CGFloat, let width: CGFloat) ->CGFloat {
  16. let font = UIFont.systemFontOfSize(fontSize)
  17. let size = CGSizeMake(width, CGFloat.max)
  18. var style = NSMutableParagraphStyle()
  19. style.lineBreakMode = NSLineBreakMode.ByCharWrapping
  20. var attributes = [NSFontAttributeName: font, NSParagraphStyleAttributeName: style.copy()];
  21. // 强转成NSString
  22. var text = self as NSString
  23. var rect = text.boundingRectWithSize(size,
  24. options: NSStringDrawingOptions.UsesLineFragmentOrigin,
  25. attributes: attributes,
  26. context: nil)
  27. return rect.size.height
  28. }
  29. ///
  30. /// @brief 把时间戳转换成“2014年12月12日 8:20:20”格式的日期字符串
  31. /// @param timeStamp 时间戳
  32. /// @return “2014年12月12日 8:20:20”格式的日期字符串
  33. ///
  34. func dateStringFromTimeStamp(let timeStamp: NSString) ->String {
  35. var formatter = NSDateFormatter()
  36. formatter.dateFormat = "yyyy年MM月dd日 HH:MM:ss"
  37. let date = NSDate(timeIntervalSince1970: timeStamp.doubleValue)
  38. return formatter.stringFromDate(date)
  39. }
  40. }

3、UIView扩展:

[objc] view plaincopyprint?
  1. import Foundation
  2. import UIKit
  3. ///
  4. /// @brief UIView的扩展方法,方便工程全局使用扩展方法来创建或者使用所有继承于UIView的控件
  5. /// @date  2014-10-09
  6. /// @author huangyibiao
  7. ///
  8. extension UIView {
  9. ///
  10. /// 获取或设置origin.x
  11. ///
  12. func originX() ->CGFloat {
  13. return self.frame.origin.x
  14. }
  15. func originX(let originX: CGFloat) {
  16. var rect = self.frame
  17. rect.origin.x = originX
  18. self.frame = rect
  19. }
  20. ///
  21. /// 获取或设置origin.y
  22. ///
  23. func originY() ->CGFloat {
  24. return self.frame.origin.y
  25. }
  26. func originY(let originY: CGFloat) {
  27. var rect = self.frame
  28. rect.origin.y = originY
  29. self.frame = rect
  30. }
  31. ///
  32. /// 获取或设置origin
  33. ///
  34. func origin() ->CGPoint {
  35. return self.frame.origin
  36. }
  37. func origin(let origin: CGPoint) {
  38. var rect = self.frame
  39. rect.origin = origin
  40. self.frame = rect
  41. }
  42. ///
  43. /// 获取或设置width
  44. ///
  45. func width() ->CGFloat {
  46. return self.frame.size.width
  47. }
  48. func width(let width: CGFloat) {
  49. var rect = self.frame
  50. rect.size.width = width
  51. self.frame = rect
  52. }
  53. ///
  54. /// 获取或设置height
  55. ///
  56. func height() ->CGFloat {
  57. return self.frame.size.height
  58. }
  59. func height(let height: CGFloat) {
  60. var rect = self.frame
  61. rect.size.height = height
  62. self.frame = rect
  63. }
  64. ///
  65. /// 获取rightX
  66. ///
  67. func rightX() ->CGFloat {
  68. return originX() + width()
  69. }
  70. ///
  71. /// 获取或设置bottomY
  72. ///
  73. func bottomY() ->CGFloat {
  74. return originY() + height()
  75. }
  76. func bottomY(let bottomY: CGFloat) {
  77. var rect = self.frame
  78. rect.origin.y = bottomY - height()
  79. self.frame = rect
  80. }
  81. }

第二步:分析好项目的特性,这几个显示的内容格式很像,因此这里使用了同一个基类,这也需要我们先封装一个基类:

BaseRefreshController

[objc] view plaincopyprint?
  1. ///
  2. /// @brief 由HotController、LatestController、TruthController继承,用于
  3. ///        统一管理数据显示
  4. /// @data   2014-10-09
  5. /// @author huangyibiao
  6. class BaseRefreshController: UIViewController,
  7. UITableViewDataSource,
  8. UITableViewDelegate,
  9. RefreshViewDelegate,
  10. JokerCellDelegate {
  11. var refreshView: RefreshView?
  12. var dataSource = NSMutableArray()
  13. var tableView: UITableView?
  14. var currentPage: Int = 1
  15. var cellIdentifier = "JokerCellIdentifier"
  16. override func viewDidLoad() {
  17. super.viewDidLoad()
  18. self.automaticallyAdjustsScrollViewInsets = false;
  19. self.view.backgroundColor = UIColor.whiteColor()
  20. // table view
  21. self.tableView = UITableView(frame: CGRectMake(0, 64, self.view.width(), kScreenHeight - 49 - 64))
  22. self.tableView?.dataSource = self
  23. self.tableView?.delegate = self
  24. self.tableView?.separatorStyle = UITableViewCellSeparatorStyle.None
  25. self.view.addSubview(self.tableView!)
  26. var nib = UINib(nibName: "JokerCell", bundle: nil)
  27. self.tableView!.registerNib(nib, forCellReuseIdentifier: cellIdentifier)
  28. // refresh view
  29. var array = NSBundle.mainBundle().loadNibNamed("RefreshView", owner: self, options: nil) as Array
  30. self.refreshView = array[0] as? RefreshView
  31. self.tableView!.tableFooterView = self.refreshView
  32. self.refreshView!.delegate = self
  33. }
  34. ///
  35. /// @brief 加载更多数据,此方法由子类调用
  36. /// @param urlString 请求地址,其中不指定page值
  37. func downloadData(#urlString: String) {
  38. let url = "\(urlString)\(self.currentPage)"
  39. self.refreshView!.startLoadingMore()
  40. HttpRequest.request(urlString: url) { (data) -> Void in
  41. if data == nil {
  42. UIAlertView.show(title: "温馨提示", message: "加载失败!")
  43. } else {
  44. var itemArray = data?["items"] as NSArray
  45. for item: AnyObject in itemArray {
  46. self.dataSource.addObject(item)
  47. }
  48. self.tableView!.reloadData()
  49. self.refreshView!.stopLoadingMore()
  50. self.currentPage++
  51. }
  52. }
  53. }
  54. ///
  55. /// UITableViewDataSource
  56. ///
  57. func numberOfSectionsInTableView(tableView: UITableView) -> Int {
  58. return 1
  59. }
  60. func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  61. return self.dataSource.count
  62. }
  63. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  64. var cell = tableView.dequeueReusableCellWithIdentifier(self.cellIdentifier, forIndexPath: indexPath) as? JokerCell
  65. cell?.delegate = self
  66. if indexPath.row < self.dataSource.count {
  67. var dataDict = self.dataSource[indexPath.row] as NSDictionary
  68. cell?.data = dataDict
  69. }
  70. return cell!
  71. }
  72. ///
  73. /// UITableViewDelegate
  74. ///
  75. func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
  76. var index = indexPath.row
  77. var data = self.dataSource[index] as NSDictionary
  78. return  JokerCell.cellHeight(data)
  79. }
  80. func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  81. var index = indexPath.row
  82. var data = self.dataSource[index] as NSDictionary
  83. let comment = CommentController()
  84. comment.jokeId = data["id"] as? String
  85. self.navigationController?.pushViewController(comment, animated: true)
  86. }
  87. ///
  88. /// JokerCellDelegate 代理方法实现
  89. ///
  90. func jokerCell(cell: JokerCell, didClickPicture picutre: String) {
  91. let browser = PhotoBrowserController()
  92. browser.bigImageUrlString = picutre
  93. self.navigationController?.pushViewController(browser, animated: true)
  94. }
  95. }

如果使用的cell不一样,那么子类需要重写对应的代理方法,像查看评论这个就需要重写:

CommentController:

[objc] view plaincopyprint?
  1. import UIKit
  2. ///
  3. /// @brief  查看评价信息
  4. /// @data   2014-10-09
  5. /// @author huangyibiao
  6. class CommentController: BaseRefreshController {
  7. // 不可空
  8. var jokeId: String?
  9. override func viewDidLoad() {
  10. super.viewDidLoad()
  11. self.title = "评论"
  12. var nib = UINib(nibName: "CommentCell", bundle: nil)
  13. self.tableView!.registerNib(nib, forCellReuseIdentifier: "CommentCellIdentifier")
  14. self.tableView!.height(kScreenHeight - 64)
  15. }
  16. override func viewWillAppear(animated: Bool) {
  17. super.viewWillAppear(animated)
  18. if let root = self.tabBarController as? RootTabBarController {
  19. root.tabBarView?.hidden = true
  20. }
  21. if self.jokeId != nil {
  22. downloadData(urlString: "http://m2.qiushibaike.com/article/\(self.jokeId!)/comments?count=20&page=")
  23. }
  24. }
  25. override func viewWillDisappear(animated: Bool) {
  26. super.viewWillDisappear(animated)
  27. if let root = self.tabBarController as? RootTabBarController {
  28. root.tabBarView?.hidden = false
  29. }
  30. }
  31. ///
  32. /// RefreshViewDelegate
  33. func refresh(refreshView: RefreshView, didClickButton button: UIButton) {
  34. if self.jokeId != nil {
  35. downloadData(urlString: "http://m2.qiushibaike.com/article/\(self.jokeId!)/comments?count=20&page=")
  36. }
  37. }
  38. ///
  39. /// UITableViewDataSource
  40. ///
  41. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  42. var cell = tableView.dequeueReusableCellWithIdentifier("CommentCellIdentifier", forIndexPath: indexPath) as? CommentCell
  43. if indexPath.row < self.dataSource.count {
  44. var dataDict = self.dataSource[indexPath.row] as NSDictionary
  45. cell?.data = dataDict
  46. }
  47. return cell!
  48. }
  49. ///
  50. /// UITableViewDelegate
  51. ///
  52. override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
  53. var index = indexPath.row
  54. var data = self.dataSource[index] as NSDictionary
  55. return  CommentCell.cellHeight(data)
  56. }
  57. override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  58. // 重写而已,以防调用父类的方法
  59. }
  60. }

这样封装好以后,下面的最新、热门、真相这三个模块就很简化了:

[objc] view plaincopyprint?
  1. import Foundation
  2. import UIKit
  3. ///
  4. /// @brief 热门 模块视图控制器
  5. /// @author huangyibiao
  6. class HotController: BaseRefreshController {
  7. ///
  8. /// @brief 生命周期函数
  9. ///
  10. override func viewDidLoad() {
  11. super.viewDidLoad()
  12. self.title = "热门";
  13. downloadData(urlString: "http://m2.qiushibaike.com/article/list/suggest?count=20&page=")
  14. }
  15. ///
  16. /// RefreshViewDelegate
  17. func refresh(refreshView: RefreshView, didClickButton button: UIButton) {
  18. downloadData(urlString: "http://m2.qiushibaike.com/article/list/suggest?count=20&page=")
  19. }
  20. }
[objc] view plaincopyprint?
  1. import Foundation
  2. import UIKit
  3. ///
  4. /// @brief 最新 模块视图控制器
  5. /// @author huangyibiao
  6. class LatestController: BaseRefreshController {
  7. ///
  8. /// @brief 生命周期函数
  9. ///
  10. override func viewDidLoad() {
  11. super.viewDidLoad()
  12. self.title = "最新";
  13. downloadData(urlString: "http://m2.qiushibaike.com/article/list/latest?count=20&page=")
  14. }
  15. ///
  16. /// RefreshViewDelegate
  17. func refresh(refreshView: RefreshView, didClickButton button: UIButton) {
  18. downloadData(urlString: "http://m2.qiushibaike.com/article/list/latest?count=20&page=")
  19. }
  20. }
[objc] view plaincopyprint?
  1. import Foundation
  2. import UIKit
  3. ///
  4. /// @brief 真相 模块视图控制器
  5. /// @author huangyibiao
  6. class TruthController: BaseRefreshController {
  7. ///
  8. /// @brief 生命周期函数
  9. ///
  10. override func viewDidLoad() {
  11. super.viewDidLoad()
  12. self.title = "真相";
  13. downloadData(urlString: "http://m2.qiushibaike.com/article/list/imgrank?count=20&page=")
  14. }
  15. ///
  16. /// RefreshViewDelegate
  17. func refresh(refreshView: RefreshView, didClickButton button: UIButton) {
  18. downloadData(urlString: "http://m2.qiushibaike.com/article/list/imgrank?count=20&page=")
  19. }
  20. }

那么剩下定制cell及动态调整内容就让大家自己去查看源码了!!!!!

想要源码吗?猛击这里

版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 上一篇处理文本中的超链接
  • 下一篇iOS中用到的3DES密码算法

转载于:https://www.cnblogs.com/Free-Thinker/p/4863450.html

Swift实现糗事百科Demo(实战项目)相关推荐

  1. Scrapy糗事百科爬虫实战代码分析

    Scrapy糗事百科爬虫实战代码分析 视频教学网址:[python爬虫_从入门到精通(高级篇)]scrapy框架.反爬.分布式爬虫 一.Scrapy糗事百科之爬取单页数据并保存 具体的创建方法可以参照 ...

  2. 网络爬虫---爬取糗事百科段子实战

    Python网络爬虫 1.知识要求 掌握python基础语法 熟悉urllib模块知识 熟悉get方法 会使用浏览器伪装技术 如果您对相关知识遗忘了,可以点上面的相关知识链接,熟悉一下. 2.爬取糗事 ...

  3. Python之爬取糗事百科段子实战

    "简说Python",选择"置顶/星标公众号" 福利干货,第一时间送达! 阅读本文大约6分钟,实战学习,老表建议你反复看,反复记,反复练. // 本文作者 王豪 ...

  4. python实现数据爬取——糗事百科爬虫项目

    python实现数据爬取--糗事百科爬虫项目 # urllib.request 请求模块 import urllib.request # re 模块使 Python 语言拥有全部的正则表达式功能. i ...

  5. Android实战——jsoup实现网络爬虫,糗事百科项目的起步

    Android实战--jsoup实现网络爬虫,爬糗事百科主界面 本篇文章包括以下内容: 前言 jsoup的简介 jsoup的配置 jsoup的使用 结语 前言 对于Android初学者想要做项目时,最 ...

  6. Python爬虫实战(1):爬取糗事百科段子

    Python爬虫入门(1):综述 Python爬虫入门(2):爬虫基础了解 Python爬虫入门(3):Urllib库的基本使用 Python爬虫入门(4):Urllib库的高级用法 Python爬虫 ...

  7. python爬虫经典段子_Python爬虫实战(1):爬取糗事百科段子

    大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...

  8. 前端开发~uni-app ·[项目-仿糗事百科] 学习笔记 ·008【首页开发】

    注:前言.目录见 https://god-excious.blog.csdn.net/article/details/105312456 文章目录 [024]page-json配置 [025]图文.视 ...

  9. pythonscrapy爬虫 崔庆才_Python爬虫实战一之爬取糗事百科段子

    大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧.那么这次为大家带来,Python爬取糗事百科的小段子的例子. 首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把 ...

  10. Python爬虫实战一之爬取糗事百科段子

    点我进入原文 另外, 中间遇到两个问题: 1. ascii codec can't decode byte 0xe8 in position 0:ordinal not in range(128) 解 ...

最新文章

  1. 蚂蚁开源增强版 SpringBoot,都有哪些骚能力?
  2. 一文详解JavaBean 看这篇就够了
  3. micro hdmi引脚定义义_臻实力芯定义:京东AMD笔记本电脑双11开门红-AMD笔记本 ——快科技(驱动之家旗下媒体)-...
  4. windows配置maven环境并换源
  5. js心跳间隔怎么确定_外墙瓷砖渗水怎么处理的?施工步骤和方法都在这啦
  6. 超时,重试,熔断,限流
  7. 修改WordPress主题导致整个站点404无法访问
  8. arduino蓝牙通讯代码_蓝牙4.0模块 无线数据传输模块 无线蓝牙串口 Arduino
  9. 使用FindBugs-IDEA插件找到代码中潜在的问题
  10. 西门子cpu指示灯含义_【技成周报28期】西门子全系列常见问题解答分享
  11. Iptables(2) - iptables命令的基本用法
  12. python netsnmp与pysnmp
  13. python将一行作为字段_Python 变量代入,指定某一行截取输出字段怎么办?
  14. 任正非:假设未来数据流量管道变粗…
  15. python当前日期时间_Python当前日期时间
  16. Atitit mybatis 简化开发与提升开发效率法 目录 1.1. 使用注解模式代替xml模式 1 1.2. 使用通用mapper代替专用mapper 1 1.3. 使用js等脚本语言来输出sq
  17. 求数的绝对值一定是正数_有理数的绝对值难,那是因为你这些知识点和题型没掌握...
  18. 精品化游戏《热血征途》掀起网页游戏大变革
  19. 刘士颉老师——德鲁克“卓有成效”管理理论的践行者,曾任宜信公司培训负责人
  20. Excel操作-跳过隐藏行粘贴

热门文章

  1. nacos修改端口号
  2. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_6_字节输出流写多个字节的方法...
  3. 二、运行盛派的Demo(看下效果)
  4. node koa2 玩起来都是中间件啊
  5. Linux Mint,Ubuntu 18 ,Deepin15.7 安装mysql 没有提示输入密码,修改root用户密码过程...
  6. python笔记-动态类型
  7. 使用hbase遇到的问题
  8. POJ 1236 Network of Schools (校园网)
  9. jQuery课堂测验
  10. 【ARM】2410裸机系列-中断处理