一个简单的私人通讯录项目,涉及手写代码UI,自定义View、model、代理,数据的正向、逆向传递,UITableView和其他常见控件的基本使用,
以及数据的持久化存储NSUserDefaults、fmdb的使用
私人通讯录App
一、搭建基础
1、自定义CTNavigationController 并将他 设置成window根控制器,将Login设置成NavigationController的根控制器2、分别建立CTLoginController、CTContactsController、CTAddController、CTEditController。一个页面对应一个Controller
二、实现CTLoginController
1、初始化界面2、当两个field都有值的时候,登录按钮才能点击
注意:有三种代理方式:
第一:addTarget
第二:设置Delegate 监听一个对象的时候
第三:添加通知(记住在dealloc中移除通知)监听多个对象的时候
这里需要监听两个field,没有对应的代理方法,这里使用通知
3、Switch:当点击自动登录时记住密码,当取消记住密码时取消自动登录
这里使用addTarget:forControlEvents:UIControlEventValueChanged,对应的事件不是鼠标点击,而是值的改变
4、优化登录
在这里将用户名和密码写实,并对用户名和密码进行了验证。
这里使用了MBProgressHUD第三方框架
5、在点击登录按钮之前,将用户名正想传递给 Login 控制器(数据的正向传递),在跳转之前,键盘收起来(退出第一响应)
--------
1.UISwitch
* UISwitch继承自UIControl,因此也能像UIButton一样监听一些事件,比如状态改变事件
* UISwitch可以通过拖线监听状态改变
* UISwitch可以通过addTarget:...方法监听状态改变
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
// 其中controlEvents参数传递的是:UIControlEventValueChanged(值改变事件)
2.监听文本框的文字改变
* 一个文本输入框的文字发生改变时,文本输入框会发出一个UITextFieldTextDidChangeNotification通知
* 因此通过监听通知来监听文本输入框的文字改变
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:textField];
// textField文本输入框的文字改变了,就会调用self的textChange方法
三、实现CTAddViewController
1、初始化界面2、当两个field都有值的时候,添加按钮才能点击
3、点击添加按钮时,将数据逆向传递给 联系人列表 控制器
数据的逆向传递是重点:设置AddViewController 的代理 为ContactViewController
Add控制器 添加完数据 之后 通过代理方式 告诉Contact 我添加完数据了,给你数据
1、在Add中编写协议、方法。
2、在Add中,添加完成的时候,告诉代理
3、在Contact中,设置代理,添加协议,实现方法
这里我们使用的是模型CTContact(将属性都写在@interface中)
/*
copy : NSString/NSMutableString/block
weak : delegate/UI控件
strong : 其他OC对象
assign : 基本数据类型(int、float。。)枚举,结构体
*/
4、我们在CTAddViewController的delegate中获取到了数据,刷新列表
表格的刷新分两步:
a、改模型数据
b、刷新表格
四、实现CTEditViewController
1、初始化界面2、刚进来的时候:两个Field不可用,右上角是编辑按钮,下方的保存按钮隐藏,cell数据传递进来
cell数据的传递时关键:当点击cell的时候,调用代理方法:- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
在这个方法中设置模型contact的值,在EditVc中定义一个CTContact 模型接受数据;
因为控制器的View都是采用的延时加载的形式,所以不能以重写setContact的方法来设置EditVc中的显示数据,我们
点击编辑按钮:phoneField成为第一响应者,保存按钮出现,编辑按钮变为取消按钮
3、点击保存按钮时,将数据逆向传递给 联系人列表 控制器
数据的逆向传递是重点:设置AddViewController 的代理 为ContactViewController
Edit控制器 添加完数据 之后 通过代理方式 告诉Contact 我添加完数据了,给你数据
1、在Edit中编写协议、方法。
2、在Edit中,添加完成的时候,告诉代理
3、在Contact中,设置代理,添加协议,实现方法
这里我们使用的是模型CTContact(将属性都写在@interface中)
4、数据的保存
a.当点击取消的时候,数据保持不变;
b.数据更改成功,点击saveBtn;
我们在CTEditViewController的delegate中获取到了数据,刷新列表
因为我们从ContactVc传递的模型数据就是EditVc中的Contact,所以地址没有改变。所以我们在ContactVc中直接刷新TableView就可以了。
刷新表格
5、自定义CTContactCell
原因:我们想要得到我们自己的cell格式,就是在一个cell下面有一个分割线,系统没有提供这样的方法,所以我们需要自定义一个CTContactCell(继承自UITableViewCell)
我们需要在CTContactVC中做更改
创建cell、传模型、返回cell
// 创建cell
CTContactCell *cell = [CTContactCell cellWithTableView:tableView];
// 设置cell数据
cell.contact = self.contacts[indexPath.row];
// 自定义setContact方法,将cell的数据在内部进行封装
- (void)setContact:(CTContact *)contact{
_contact = contact;
self.textLabel.text = contact.name;
self.detailTextLabel.text = contact.phone;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;
在CTContactCell初始化的时候,会调用这个方法一次,所以我们需要在这个方法中自定义一个带有分割线的ContactCell。
现在分割线的主流做法就是:将原有的tableView的分割线格式取消,然后再在这个方法中自定义一个高度为1的UIView
// 我们在这个方法中获取的是CTContactCell更改后的尺寸,是最真实的尺寸,所以我们需要在这个方法中设置他的frame
- (void)layoutSubviews{
[super layoutSubviews];
}
五、数据持久化
最后我们使用NSUserDefaults *default = [NSUserDefaults standardUserDefaults];来对系统设置进行存储。自动登录,记住密码,用户名,密码。