★房贷计算器 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 | |
3 | 4 | 5 | 6 | 7 | ||
10 | 11 | 12 | 13 | 14 | ||
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-]];
NSString *everyMonthDiffString = [moneyFormatter stringFromNumber:self.everyMonthDiff[row-]];
NSString *evertMonthInterestString = [moneyFormatter stringFromNumber:self.everyMonthInterest[row-]];
[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-]];
NSString *everyMonthDiffString = [moneyFormatter stringFromNumber:self.everyMonthDiff[row-]];
NSString *evertMonthInterestString = [moneyFormatter stringFromNumber:self.everyMonthInterest[row-]];
[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. 利率更新提示(更新当天);
★房贷计算器 APP的更多相关文章
- Android实战项目:房贷计算器
APP源码已上传到我的GitHub:https://github.com/zdm-code/Android-learning/tree/master/android_learning/mortgage ...
- JavaScript:综合案例---房贷计算器的实现
房贷计算器的实现 (可以使用的编辑器:webStrom.subLime.notePad++.editPlus) 输入数据: 平方单价 70,000.00 元/平方 B1 租金 382.50 元/平方 ...
- C# 房贷计算器
设计背景 百度小程序中的房贷计算器不能满足我个人的需求,故而开发一个.NET小程序.希望后期能用JS重写,发布在网上供大家使用. 设计思路 根据百度公式:等额本息月还款 = [贷款本金×月利率×(1+ ...
- 复利计算器app发布
复利计算器app发布 抱歉:由于无法实现服务端的持续开启,发布的app仅为简单的单机版,暂时舍弃了c/s版本的一些功能,如:投资动态管理功能. 应用详情博客:请点击这里 apk下载地址1(百度手机助手 ...
- 纯js房贷计算器开源
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- PHP房贷计算器代码,等额本息,等额本金
debx(); function debx() { $dkm = 240; //贷款月数,20年就是240个月 $dkTotal = 10000; //贷款总额 $dknl = 0.0515; //贷 ...
- IOS之计算器实现
本文利用ios实现计算器app,后期将用mvc结构重构 import UIKit class CalculViewController: UIViewController { @IBOutlet we ...
- 哪些产品不用开发原生APP,微信公众号就够了?
最近一阶段H5技术被推到高峰,很多人认为借助H5就能利用微信公众号取代APP原生应用了,而事实是怎么样的?这里我从产品层做一个客观分析. 一,原生APP总体趋势 要谈APP是否会被微信取代,那么必须回 ...
- 手游与App测试如何快速转型? —— 过来人科普手游与App测试四大区别
随着智能设备的普及和移动互联网的兴起,各家互联网巨头纷纷在往移动端布局和转型,同时初创的移动互联网公司也都盯着这个市场希望分一杯羹.在这个大环境下,互联网的重心已经慢慢从Web端转向了移动端,而移动端 ...
随机推荐
- 解决overflow: auto在Ios中滑动不流畅
[bug]—— H5页面在 ios 端滑动不流畅的问题 IOS系统的惯性滑动效果非常6,但是当我们对div加overflow-y:auto;后是不会出这个效果的,滑动的时候会感觉很生涩.怎么办? ...
- Codevs 3409 搬运礼物
3409 搬运礼物 CodeVS原创 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 青铜 Bronze 题解 题目描述 Description 小浣熊松松特别喜欢交 ...
- Java 虚拟机(Java Virtual Machine)
Java 编译器将 Java 程序编译成虚拟机能够识别的二进制代码,这种代码称为字节码(Bytecode).字节码就是虚拟机的机器指令,它与平台无关,有统一的格式,不依赖于具体的硬件环境,只运行在 J ...
- extern用法详解(转)
1 基本解释 extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义. 另外,extern也可用来进行链接指定. 2 问题:ext ...
- Visual Studio 2015、2013、2012、2010、2008、2005各版本下载+有效密钥激活
Visual Studio是微软发布的一个集成开发工具,业内一般简称为VS,广泛应用于Windows软件开发.网站开发等,是目前十分流行的windows应用程序的集成开发工具,如果大家不了解,可以简单 ...
- VLAN-3-VLAN Trunk:ISL和802.1Q
(1)ISL和802.1Q概念 通过使用VLAN Trunk链路,设备可以通过一条链路发送去往多个vlan的流量.为了知道数据帧属于哪个vlan,发送方会添加原始以太网数据帧的头部,这 ...
- python 基础(十五) socket编程
SOCKET TCP协议: 有请求 有响应 称之为 tcp协议 是面向连接的协议 就是在收发数据之前 必须先要建立一个可靠的链接 三次握手 如:网站 UDP协议: 是一个非链接的协议 传输之前不需要键 ...
- 转 open_cursors参数设置调优
https://www.cnblogs.com/Peyton-for-2012/archive/2013/05/07/3065058.html
- [已读]高性能JavaScript
值得多读几遍的书.
- var声明提前 undefined
1.同一代码块内,所有var声明都提前: 2.var 变量的初始化不提前,按顺序执行: 3."undefined"和undefined都存在于window中: 4.if(" ...