iOS 高仿Timi记账

607 查看

写在最前面:

其实本文应该早在两个月之前就该写完的,由于当时找工作,种种原因搁置到现在才写完。
本文不可能把每一个点都能写到,如果真要一个点一个点的写,可能得写1w+字吧。再说时隔两个多月没碰这个项目了,多多少少都忘了一些。我尽可能把当时在写这个项目遇到的各种坑写详细。如果在看本文或者demo的时候有不明白的地方可以在Github上面提issue或者简书简信我也可以。
温馨提示:看文章的时候结合代码一起看,效果会更佳哟。
目前完成进度70%,由于时间的关系(临近期末,各种事情的原因…),剩下的30%未能完成,后面抽空完成吧。
项目采用MVC设计模式
本人还属于菜鸟级别,代码写得不规范,望见谅!
如果项目中同样的问题,你有更好的办法解决请告诉我,让我们一起学习。

废话说了一大堆,开始进入正题!!!

项目视频演练 -> 点我

Demo ->Timi 不要忘记star支持哟

高仿版本:3.6.1

使用语言:Objective-C

开发工具及调试神器:Xcode 7.3.1,Reveal 1.6.3

用到的三方库及扩展库

NAME EXPLAIN
Masonry 纯代码Autolayout
MBProgressHUD 未使用,后更改为使用SVProgressHUD
MMDrawerController 抽屉
SVProgressHUD HUD
YYText 著名库YYKit下的一个富文本
iCarousel 一个类似UIScrollView的控件
ColorCube 图片颜色提取
UITextView_PlaceHolder 给UITextView添加PlaceHolder
SZCalendarPicker 日历
TYPagerController 左右滚动ViewController VTMagic
Realm 移动端数据库新王者

数据库设计

TMBill(账单)

KEY IDENTITY COLUMN DATA TYPE LENGTH ALLOWED NULL DEFAULT DESCRIPTION
billID NSString 64 主键
dateStr NSString 10 当前年月日 时间
reMarks NSString 40 nil 备注
remarkPhoto NSData nil 图片备注
isIncome BOOL 1 0 类型(收支)
money float 13 0 金额
FK category TMCategory 类别
FK book TMBooks 账本
11959078-853d783b9c189b58
TMBill(账单).png

TMCategory(类别)

KEY IDENTITY COLUMN DATA TYPE LENGTH ALLOWED NULL DEFAULT DESCRIPTION
categoryID NSString 64 主键
categoryImageFileNmae NSString 64 类别icon文件名
categoryTitle NSString 3 类别标题
isIncome BOOL 1 类型(收支)
12959078-eb1a791ce022a422
TMCategory(类别).png

TMBook(账本)

KEY IDENTITY COLUMN DATA TYPE LENGTH ALLOWED NULL DEFAULT DESCRIPTION
bookID NSString 64 主键
bookName NSString 6 账本标题
imageIndex int 2 账本对应icon下标
bookImageFileName NSString 64 类别icon文件名
13959078-21309f82d3353baf
TMBook(账本).png

TMAddCategory(新增类别)

KEY IDENTITY COLUMN DATA TYPE LENGTH ALLOWED NULL DEFAULT DESCRIPTION
categoryID NSString 64 主键
categoryImageFileNmae NSString 64 类别icon文件名
isIncome BOOL 1 类型(收支)
14959078-3e24d45c96f1a226
TMAddCategory(新增类别).png

TMCategory(类别),TMAddCategory(新增类别)都是采用plist表的方式先存储。当App每次启动的时候就会先检查数据库对应的表是否为空,为空则从plist表读取数据,存储到本地数据库。

项目整体结构

15959078-5bf4eb18f7c839c9
TimiStructure.png

温馨提醒

项目里面95%都是使用的纯代码方式布局(Masonry),如果不懂的Masonry纯代码布局的请先去了解一下。传送门=>串哥的深入讲解 AutoLayout 和 Masonry

时光轴界面(HomePageViewController)

UI布局之header部分(TMHeaderView)

17959078-26524816d97344b9
Paste_Image.png

其实headerView部分没有什么好说的,那个饼图是用UIBezierPathCAShapeLayer绘制而成,我把它单独封装出来了,因为在后面的饼图部分也用到了。关于饼图的加载数据时候的动画我是使用的CABasicAnimation具体的操作可以看demo的对应文件(TMPieView)

UI布局之数据显示部分(HomePageViewController | TMTimeLineCell)

18959078-ae001ee1ecaea501
Paste_Image.png

数据的显示全部在一个section里面,并没有分section显示,而且cell也只有一个样式,我是通过收支类型来判断的该那边显示数据。
时间轴上面,相同时间(同一天)时间label和金额label以及时间点不显示出来,我是在模型层加了一个BOOL变量来判断,同时在获取数据之后进行数据的重置,具体的操作可以看HomePageViewControllergetDataAndResetBill函数。
然后在自定义cell(TMTimeLineCell)重写timeLineBill属性,通过判断来显示数据。
下图应该清楚的看懂整个cell的布局

19959078-17722f19aa068eb9
Paste_Image.png

其实这种做法并不好,一个cell是能完成,但是代码看起来就有点乱糟糟的感觉,正确的做法是应该有两种样式的cell。分别是账单类型为收入,账单类型为支出两种样式。

很多人都应该碰到过,滑动tableView的时候Cell的数据会出现混乱,我是这样解决的,在自定义cell重写- (void)prepareForReuse函数,将cell里面的控件元素的属性和对象统统置为nil。

细心的人可能看到了我在下滑tableview的时候,中间的时光轴线也跟着变长。当我下滑到一定程度,然后松手就会push到新增账单界面,而且这个push动画不是系统自带的push动画。
下面我一一为大家解答:

时光轴的线条是怎么变长的?

第一步、我是新增的一个UIView,默认frame为(SCREEN_SIZE.width-1)/2,0 , 1, 0),将它加到tableview上面。

第二步、在UIScrollViewDelegate的 - (void)scrollViewDidScroll:(UIScrollView *)scrollView 代理函数里面获取滑动的y值。判断其方向并重新设置dropdownLineView的frame即可

时光轴界面到添加账单(修改账单)界面的转场动画(LYPushTransition,LYPopTransition)

使用的是自定义的转场动画,具体如何使用请看喵神KittenYang 的blog,推荐几句代码快速集成自定义转场效果+全手势驱动
1.首先定一个class,继承至NSObject,遵守UIViewControllerAnimatedTransitioning协议。
2.需要实现两个方法