【我的第一个App——私人通讯录】项目需求、实现技术点总结

时间:2023-01-13 15:08:02

一个简单的私人通讯录项目,涉及手写代码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];来对系统设置进行存储。
自动登录,记住密码,用户名,密码。