专栏名称: Cocoa开发者社区
CocoaChina苹果开发中文社区官方微信,提供教程资源、app推广营销、招聘、外包及培训信息、各类沙龙交流活动以及更多开发者服务。
目录
相关文章推荐
花果科技  ·  iOS 18.4 ... ·  16 小时前  
花果科技  ·  iOS 18.4 ... ·  16 小时前  
51好读  ›  专栏  ›  Cocoa开发者社区

如何在iOS开发中更好的做假数据?

Cocoa开发者社区  · 公众号  · ios  · 2017-07-05 11:58

正文

当工期比较紧的时候,项目开发中会经常出现移动端等待后端接口数据的情形,不但耽误项目进度,更让人有种无奈的绝望。所以在开发中,我们常常自己做些假数据,以方便开发和UI调试。然而做假数据方法不同,效率和安全性都各不同,有时稍有不慎,还会产生很大的bug。因此本文拟结合我在贝聊的开发经验,讲一讲我们组在iOS开发中曾经用过的做假数据的方法及其优劣。


示例项目


为方便下文的说明,本文主要以贝聊家长版app发现首页的热门帖子列表的实现为例。热门帖子列表的样式如下图:



这是比较常见的列表,用常用的UITableView实现即可,但需要自定义一个的UITableViewCell的子类ExploreTableViewCell。项目中,ExploreTableViewCell并没有用xib实现(因为xib日后不好修改,且代码复用性差),而是通过SnapKit用纯代码布的局,具体的布局代码大致如下:


import UIKit

import SnapKit

class  ExploreTableViewCell: UITableViewCell {

let thumbnailImageView: UIImageView

let titleLabel: UILabel

let avatarImageView: UIImageView

let authorNameLabel: UILabel

let viewCountLabel: UILabel

let commentCountLabel: UILabel

//...其他属性


override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

//创建view

thumbnailImageView = UIImageView()

titleLabel = UILabel()

avatarImageView = UIImageView()

authorNameLabel = UILabel()

viewCountLabel = UILabel()

commentCountLabel = UILabel()


//...其他view的创建


super.init(style: style, reuseIdentifier: reuseIdentifier)

//设置view

titleLabel.numberOfLines = 2

titleLabel.textColor = UIColor.black

titleLabel.snp.makeConstraints { (make) -> Void in

make.left.equalTo(thumbnailImageView.snp.right).offset(15)

make.right.equalTo(contentView.snp.right)

make.top.equalTo(contentView.snp.top)

}

//...其他view的设置

}


//...其他业务代码

}


源码中写死


源码中写死数据是最便捷的假数据做法,项目很赶时,为最快速的看到UI效果,一般都会采取这种假数据方式。比如在上述热门帖子列表示例项目中,为查看整个ExploreTableViewCell的布局效果,在titleLabel等subview的设置位置,直接写死假数据。


//...其他代码

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

//...其他初始化代码


//写死的假数据代码

titleLabel.text = "这是一个标题这是一个标题这是一个标题这是一个标题这"

thumbnailImageView.image = UIImage(named:"sampleImage")

avatarImageView.image = UIImage(named:"sampleImage")

authorNameLabel.text = "作者名"

viewCountLabel.text = "1000"

commentCountLabel.text = "1000"


//...其他初始化代码


}

//...其他代码


源码中写死假数据虽然方便,但稍有不慎就容易直接上线上环境(因为测试在测试时一般都会有数据,假数据被遮盖了),演变成一个有可能非常严重也有可能很轻的bug(贝聊就切实出现过这样的bug,而且还是个影响广泛的大bug),为安全起见,所有写死的假数据都应该包在条件编译宏内。


//...其他代码

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

//...其他初始化代码


//写死的假数据代码,包裹在条件编译宏内

#if DEBUG

titleLabel.text = "这是一个标题这是一个标题这是一个标题这是一个标题这"

thumbnailImageView.image = UIImage(named:"sampleImage")

avatarImageView.image = UIImage(named:"sampleImage")

authorNameLabel.text = "作者名"

viewCountLabel.text = "1000"

commentCountLabel.text = "1000"

#endif

//...其他初始化代码


}

//...其他代码


包在条件编译宏内,就可以保证不污染正式环境的代码,从而保证安全性。


利用单元测试的网络请求stub做假数据


在源码中写死假数据,有以下三个缺点:


  • 污染源代码

假数据写在源代码中,即使用宏包裹起来,只是保证了一定的安全性,但依然污染了源代码,如果上线前忘了把假数据代码移除,它一直会残留在源代码中,而且还会一直影响DEBUG环境的调试。

  • 假数据散落四处,无法集中管理

本文示例代码的假数据虽然写在一块,但在实际开发中,并不是所有的UI代码都在一个文件中。即使在一个文件内,往往各个属性的初始化和设置也不在一个方法内。代码一多,基本很难管理。

  • 扭曲了数据的正确流通

正确的数据产生方式,应该是发一个网络请求,然后把请求回来的数据转成model,最后通过model给各个UI组件填充数据。而在源代码中写死假数据,直接打乱了数据的正确流通,这会使得整个开发的逻辑是颠倒的,不但使开发更容易出bug,而且逻辑流的切换带来的开发效率和开发感受都很差。


较好的假数据方式,应该尽可能的不污染源代码,不扰乱正常的数据流通,而且能集中管理。在研究单元测试时,我无意中发现stub某个页面请求数据的网络请求即可达到这种完美的假数据效果。


首先按正常的流程开发整个功能,(在开发中,我总是倾下于先创建Model,而不是先写UI)


  1. 创建Model

  2. 创建ViewController

  3. 创建View等UI元素

  4. 在ViewController中完成网络请求的发起,并完成从网络数据到Model的转换

  5. 应用Model填充UI


整个功能开发按照有真实网络请求进行,但事实上并没有网络请求,因为后台并未搭好,没关系,先按照后台给出的接口和数据格式定义,创建一个本地JSON文件。对于本文的示例(假定只有列表数据)来说,文件名暂为hotTopics.json,内容大致如下(贝聊发现首页实际上有很多其他元素,网络请求返回的JSON也比这个复杂的多):


{

hotTopics: [

{

"title": "这是一个标题这是一个标题这是一个标题",

"thumbnail": "https://api.beiliao.com/explore/image/fdlafjlfp34523.jpg",

"author": "小黄老师",

"authorAvatar": "https://api.beiliao.com/explore/image/fdlafjlfp34523.jpg",

"commentCount": 1000,

"viewCount": 3000

},

{

"title": "这是另外一个标题这是另外一个标题这是另外一个标题",

"thumbnail": "https://api.beiliao.com/explore/image/fdla32131fjlfp34523.jpg",

"author": "小李老师",

"authorAvatar": "https://api.beiliao.com/explore/image/fdl232afjlfp34523.jpg",

"commentCount": 1030,

"viewCount": 3400

}

]

}


然后在ViewController中stub本ViewController中所有的网络请求,我在开发中用的是 OHHTTPStubs ,大致的代码如下:


class ExploreViewController: UITableViewController {







请到「今天看啥」查看全文