★房贷计算器 APP
一、目的
1. 这是一个蛮有用的小工具
2. 之前看了很多demo,第一次来完全的自己实现一个APP
3. 完成之后提交 App Store
4. 作为Good Coder的提交审核材料
二、排期
周日 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 |
18 | ||||||
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 | 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
7.18-7.19:完成MRD设计
7.20-7.24:完成技术框架搭建,包括:MVC、基类设计和功能分工、Pod库的选取
7.25-8.9:完成全功能第一版
8.10-8.16:整理优化
三、MRD
7.20
第一步 模仿App Store的房贷计算器设计UI(工具:keynote)
第二步 增加新的功能
1. 提前还款功能
2. 央行降息后还款金额变化
3. 公积金贷款额度查询
4. 点击非编辑区域,收起键盘
四、技术框架
7.20
1. 工程名:HouseLoanCal,所有类前缀:HLC
2. Controller
底部是UITabBarController
公积金贷款:HLCProvidentFundLoanController
商业贷款:HLCCommercialLoanController
混合贷款:HLCMixedLoanController
继承自HLCLoanController,继承HLCTableViewController,继承自UITableViewController
3. View
基本上靠TableView可以实现,不需要专门的View
4. Model
首先,三种贷款模式(公积金贷款、商业贷款、混合贷款),都可以归结为一,即贷款金额+贷款利率
公积金贷款: 贷款金额=贷款金额 贷款利率=贷款利率
商业贷款: 贷款金额=贷款金额 贷款利率=贷款利率*折扣
组合贷款: 贷款金额=公积金贷款金额+商业贷款金额 贷款利率=(公积金贷款金额*公积金贷款利率+商业贷款金额*商业贷款利率*折扣)/(公积金贷款金额+商业贷款金额)
输入数据
贷款金额:单位为万元,其他金额数字基本为元
贷款利率:默认值为当前利率(目前暂时未找到免费的利率接口,先写在本地)
贷款期限:必须为>0整数
还款日期:存的是年月日,显示的是年月,默认值为当前日期
还款方式:枚举类型,决定了计算的结果
输出数据
折合利率:
累计支付利息:
累计还款总额:
每期还款、每期本金、每期利息
当为等额本息时,头部显示每期还款,下面列表显示本金/利息
当为等额本金时,头部显示每期本金,下面列表显示还款/利息
下面的列表行数=贷款期限*12
5. 设置里面
版本:写死
评分:跳转到App Store
推荐给朋友:调起分享SDK
五、实现中遇到的问题和解决方案
7.21
问题1
controller的框架搭建起来,运行了一次发现 navigationItem 的 title 未显示,排查发现 controller 的viewDidLoad没有运行进去
解决方法
HLCBaseTableViewController 继承了 UITableViewController,它本来就有一个属性 tableView
self.tableView 的操作移到 viewDidLoad 即可
7.27
问题2
自定义的cell,点击之后,分割线会消失
7.29
问题3
之前是Setting页面定义了多个cell,打算整合成一个,用cellstyle来区分,类似 UITableViewCellStyle
8.17
等额本息 计算公式:
每月本息 = 贷款本金 * {月利率*[(1+月利率)^还款月数]} / {[(1+月利率)^还款月数] – 1}
等额本金 计算公式:
每月本息 = (贷款本金/还款月数)+(本金-已归还本金累计额)*每月利率
8.24
NSNumber 转 NSString
最初的做法如下,缺点是显示的金额会带一个$符号
NSNumberFormatter *numFormatter = [[NSNumberFormatter alloc] init]; numFormatter.numberStyle = NSNumberFormatterCurrencyStyle; str = [numFormatter stringFromNumber:num];
解决方法
NSNumberFormatter *moneyFormatter = [[NSNumberFormatter alloc] init]; [moneyFormatter setPositiveFormat:@"###,##0.00"]; str = [moneyFormatter stringFromNumber:num];
8.25
实现了公积金贷款页的输入、输出,但是发现,上滑后滑回,每一期列表数据会错乱,怀疑跟复用同一个cellIdentifier有关,排查一下
错误代码如下:
static NSString *cellIdentifier = @"OutputDetailCellIdentifier"; HLCLoanOutputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (!cell) { cell = [[HLCLoanOutputTableViewCell alloc] initWithHLCStyle:HLCLoanOutputTableViewCellStyleSmall reuseIdentifier:cellIdentifier]; [cell setTitle:[NSString stringWithFormat:@"第%ld期", row-1]]; NSString *everyMonthDiffString = [moneyFormatter stringFromNumber:self.everyMonthDiff[row-2]]; NSString *evertMonthInterestString = [moneyFormatter stringFromNumber:self.everyMonthInterest[row-2]]; [cell setDetail:[NSString stringWithFormat:@"%@/%@", everyMonthDiffString, evertMonthInterestString]]; } return cell;
正确做法如下:
static NSString *cellIdentifier = @"OutputDetailCellIdentifier"; HLCLoanOutputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (!cell) { cell = [[HLCLoanOutputTableViewCell alloc] initWithHLCStyle:HLCLoanOutputTableViewCellStyleSmall reuseIdentifier:cellIdentifier]; } [cell setTitle:[NSString stringWithFormat:@"第%ld期", row-1]]; NSString *everyMonthDiffString = [moneyFormatter stringFromNumber:self.everyMonthDiff[row-2]]; NSString *evertMonthInterestString = [moneyFormatter stringFromNumber:self.everyMonthInterest[row-2]]; [cell setDetail:[NSString stringWithFormat:@"%@/%@", everyMonthDiffString, evertMonthInterestString]]; return cell;
每次去调用 tableView:cellForRowAtIndexPath: 首先会调用 dequeueReusableCellWithIdentifier 判断cell池中是否有可重用的cellIdentifier,若有则直接用,若没有则重新init一个
这次出的问题在于,对于cell上面的textLabel操作,错放在了if(!cell) {//…} 里面,导致若有可重用的,会直接返回cell,而不会对textLabel处理
解决方法就是把对cell的处理挪到if判断的外面
公积金贷款页基本功能已经实现,梳理一下存在的问题:
1. 计算结果有误差(100万30年5.0等额本息,累计利息有1.36元误差)
等额本金是准的,应该是等额本息的计算方法中精度问题引入了误差;
发现是AppStore的房贷计算器计算有误差,我的计算方法和精度是ok的
done
2. 贷款利率需要设定默认值
done
3. 重置后,贷款期限和贷款时间未被重置
4. 每一期加上时间
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setMonth:i];
NSDate *monthDate = [calendar dateByAddingComponents:dateComponents toDate:self.loanDate options:0];
done
5. tableViewCell无上分割线
解决方法是viewForHeaderInSection 里面 加一个下分割线
done
6. 输入为空点击计算会Crash
done
7. 重置功能
done
8. 完成商业贷款、组合贷款两个页面
done
9. 在iPhone 6/6p上的尺寸适配问题
done
10. 上滑时,header不要吸顶
解决方法一:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y <= kHLCHeightForCellHeader && scrollView.contentOffset.y >= 0) {
scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (scrollView.contentOffset.y >= kHLCHeightForCellHeader) {
scrollView.contentInset = UIEdgeInsetsMake(-kHLCHeightForCellHeader, 0, 0, 0);
}
}
发现吸顶的问题是解决了,但是下滑后再上滑回来,顶部会部分被navigationBar遮挡
解决方法二:
分割区域不用header实现,而是每个section底部加一个cell
done
11. 好评跳转功能
done
12. 推荐给朋友的分享功能(微信好友、朋友圈、微博)
友盟(分享、统计SDK)
分享:
http://dev.umeng.com/social/ios/quick-integration
接入微信SDK时,会报一片
“_sqlite3_prepare_v2”, referenced from:
_execute_prepared_config_stmt in libWeChatSDK.a(MTAWXOStore.o)
_execute_prepared_events_stmt in libWeChatSDK.a(MTAWXOStore.o)
解决方法:
在Link Binary With Libraries 中依次加入 libsqlite3.dylib ,libz.dylib, libc++.dylib添加后就可以编译通过
(注意:Xcode7之后,.dylib库需要换成同名的.tbd)
iOS9之后,schema跳转需要在Info.plist中加一个LSApplicationQueriesSchemes的数组值
分别加上 weixin, wechat, 微信 appid 三项
https://open.weixin.qq.com
http://open.weibo.com
http://open.qq.com
微博SDK接入(注意iOS9有更新,需要下2015.9.29最新的sdk)
问题1
Undefined symbols for architecture arm64:
“_OBJC_CLASS_$_CTTelephonyNetworkInfo”, referenced from:
objc-class-ref in libWeiboSDK.a(WBSDKPhoneCountryView.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解决方法:
TARGETS-Build Phases-Link Binary With Libraries
加上 CoreTelephony.framework
问题2
-[NSConcreteMutableData wbsdk_base64EncodedString]: unrecognized selector sent to instance 0x14758e840
解决方法:
Target->Buid Settings->Linking 下 Other Linker Flags 项添加-ObjC
问题3
打开了微博客户端,提示“sso package or sign error”
解决方法:
http://dev.umeng.com/social/ios/operation#3
需要在友盟后台绑定第三方账号
绑定地址:http://umeng.com/apps
选择app-社会化分享-新浪微博填上 App Key 和 App Secret
done
13. 给每个Item做个图标
初步想法是,一个圈分别加上 公、商、组三个字,设置的就保留螺丝的图标
最终用sketch绘制
代码如下
1 UIImage *tabImage = [UIImage imageNamed:@"icon_profund_normal"];
2 UIImage *tabSelectImage = [UIImage imageNamed:@"icon_profund_height"];
3 tabSelectImage = [tabSelectImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
4 self.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"公积金" image:tabImage selectedImage:tabSelectImage];
注意:要加上第3行,表示选中时的图标保持原样,不做渲染
如果不写上这句,图片做渲染之后,就会变成实心的
done
14. App lcon
Sketch绘制
整体布局与系统的计算器类似,房子和人命币图案寓意房子和贷款,加减符号寓意计算器
配色上,橘色和蓝色取得是IEEE官网的配色,比较喜欢
这个icon想了一晚上,最终比较满意
done
15. app名字
极简房贷计算器
done
16. 实时获取当前时间的贷款利率
这个需要个server,先看看有没有现成的,不行的话看看用python写一个
17. 支持夜间模式
配色可以考虑参考 N Stats
18. 版本号自动配置
// 版本号
#define HLC_APP_VERSION ([[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"])
// 使用
[cell setTitle:@"当前版本"];
[cell setContent:[NSString stringWithFormat:@"%@", HLC_APP_VERSION]];
配置的位置
TARGET 选择项目 – General – Identity – Version
填1.0.0
另外下面的 Build 可以填1.0.0.0
done
19. 下滑 支持把键盘收起
加一句即可
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
done
20. 贷款期限用自定义Picker来实现
修改过程中,出现:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)
这是请求了空指针
查到原因:
// 贷款期限
@property (nonatomic, assign strong) NSNumber *loanPeriod;
这个类型,之前是NSInteger,后来为了兼容小数而改成NSNumber,但是忘了更改类型,导致出血空指针
done
21. 数组叠加bug
复现步骤:先选择30年,计算一次,结果是360期;再选择20年,计算一次,理论应该是240期,但现在是600期
解决方法:
// 计算前清空之前的结果
[self.eachInterest removeAllObjects];
[self.eachMonth removeAllObjects];
[self.eachPrincipal removeAllObjects];
[self.eachPrincipalPlusInterest removeAllObjects];
[self.eachDiff removeAllObjects];
这种NSMutableArray类型,每次计算前,需要清空
done
2015.10.9
1.0.0 版本已上架
http://itunes.apple.com/app/id1043888133
友盟统计
http://www.umeng.com/apps
Bug1:
Deployment Target 误选成8.4 导致只能是8.4版本即以上才能下载,下个版本修复
Bug2:
在6和6p上没有做好屏幕适配,只是单纯的放大版
2015.10.27
提交Good Cooder,被驳回,原因一是代码逻辑太简单,二是没用单测(本想用UI Testing代替单测,被说这是可以录制的,不可)
先不提交了,开始着手1.1.0版本改造
2015.10.28
1.1.0版本新增功能:
1. 实现实时更新最新利率,利率选择改成Picker形式,利率值与利率更新时间对应,同时也可以支持自定义输入,默认选中最新利率;
2. 折扣改成常见折扣Picker选择,也可支持自定义输入;
3. UI优化;
4. bug修复;
5. 利率更新提示(更新当天);