这里给出大部分基本的代码
联系人模型对象:
#import "NJContatc.h" @implementation NJContatc - (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeObject:self.phoneNumber forKey:@"number"]; } - (id)initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { self.name = [aDecoder decodeObjectForKey:@"name"]; self.phoneNumber = [aDecoder decodeObjectForKey:@"number"]; } return self; } @end
登录控制器中:
1.在viewDidLoad页面刚载入进来的时候,
给两个文本输入框加入通知 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
并注冊监听文本变化 [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.acountField]
2.因为记住password和自己主动登录都属于偏好设置,所以这样的数据要保存到偏好设置中。第一次载入要去除信息:
NSUserDefaults *defaults = [NSUserDefaults standarUserDefaults];
3.使用完通知后,须要移除监听
[[NSNotificationCenter defaultCenter] removeObserver:self];
4.注意两个Switch的逻辑
取消记住password,肯定也取消了自己主动登录
选择了自己主动登录,肯定勾选了记住password
5.在点击登录button之后,须要加入一些特效。此时能够使用别人写的HUD,并设置延迟几秒跳转,简单介绍模仿网络请求延迟
使用dispatch_after snippet - GCD Dispatch After 方法,设置延迟时间可块内容
6.点击成功后。通过设置segue的identifier的值:login2contact 。
使用 [self performSegueWithIdentifier:@"login2contact" sender:@"jonathan"];跳转到联系人界面(这是手动运行segue)
7.在成功跳转之前。还须要拿到segue的目标控制器
在固定的prepareForSegue方法中通过[segue.destinationViewController],拿到目标页面的控制器
#import "NJLoginViewController.h" #import "MBProgressHUD+NJ.h" #define NJAccount @"account" #define NJPwd @"pwd" #define NJRemPwd @"remPwd" #define NJAutoLogin @"autoLogin" @interface NJLoginViewController ()<UITextFieldDelegate> /** * 账号输入框 */ @property (weak, nonatomic) IBOutlet UITextField *accountField; /** * password输入框 */ @property (weak, nonatomic) IBOutlet UITextField *pwdField; /** * 登录button */ @property (weak, nonatomic) IBOutlet UIButton *loginBtn; /** * 点击记住password */ - (IBAction)remPwdChange:(id)sender; /** * 点击自己主动登录 */ - (IBAction)autoLoginChange:(id)sender; /** * 记住password */ @property (weak, nonatomic) IBOutlet UISwitch *remPwdSwitch; /** * 自己主动登录 */ @property (weak, nonatomic) IBOutlet UISwitch *autoLoginSwitch; /** * 点击登录button */ - (IBAction)loginOnClick:(UIButton *)sender; @end @implementation NJLoginViewController - (void)viewDidLoad { [super viewDidLoad]; // 监听文本输入框的改变 // 1.拿到通知中心 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 2.注冊监听 // 注意点: 一定要写上通知的公布者 [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.accountField]; [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.pwdField]; // 3. 回显数据(读取保存的偏好设置信息) NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // 设置账号 self.accountField.text = [defaults objectForKey:NJAccount]; // 设置password // 推断是否须要记住password // BOOL isSavePwd = [defaults boolForKey:NJRemPwd]; // [self.remPwdSwitch setOn:isSavePwd animated:YES]; [self.remPwdSwitch setOn:[defaults boolForKey:NJRemPwd] animated:YES]; if (self.remPwdSwitch.isOn) { self.pwdField.text = [defaults objectForKey:NJPwd]; } // BOOL isAutoLogin = [defaults boolForKey:NJAutoLogin]; [self.autoLoginSwitch setOn:[defaults boolForKey:NJAutoLogin] animated:YES]; if (self.autoLoginSwitch.isOn) { // 自己主动登录相当于调用登录方法 [self loginOnClick:nil]; } } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)textChange { self.loginBtn.enabled = (self.accountField.text.length > 0 && self.pwdField.text.length > 0); } - (IBAction)remPwdChange:(id)sender { // 1.推断是否记住password if (self.remPwdSwitch.isOn == NO) { // 2.假设取消记住password取消自己主动登录 // self.autoLoginSwitch.on = NO; [self.autoLoginSwitch setOn:NO animated:YES]; } } - (IBAction)autoLoginChange:(id)sender { // 1.推断是否自己主动登录 if (self.autoLoginSwitch.isOn) { // 2.假设自己主动登录就记住password [self.remPwdSwitch setOn:YES animated:YES]; } } - (IBAction)loginOnClick:(UIButton *)sender { // 加入蒙版禁止用户操作, 而且提示用户正在登录 [MBProgressHUD showMessage:@"正在拼命载入ing...."]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (![self.accountField.text isEqualToString:@"lnj"]) { // 3.登录成功后移除蒙版 [MBProgressHUD hideHUD]; [MBProgressHUD showError:@"username不对!!!"]; return; } if (![self.pwdField.text isEqualToString:@"123"]) { // 3.登录成功后移除蒙版 [MBProgressHUD hideHUD]; [MBProgressHUD showError:@"password不对!!!"]; return; } // 3.登录成功后移除蒙版 [MBProgressHUD hideHUD]; // 4.假设正如,跳转到联系人界面(手动运行segue) [self performSegueWithIdentifier:@"login2contatc" sender:@"jonathan"]; // 5.保存用户数据 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:self.accountField.text forKey:NJAccount]; [defaults setObject:self.pwdField.text forKey:NJPwd]; [defaults setBool:self.remPwdSwitch.isOn forKey:NJRemPwd]; [defaults setBool:self.autoLoginSwitch.isOn forKey:NJAutoLogin]; [defaults synchronize]; }); } // 在segue跳转之前调用, 会传入performSegueWithIdentifier方法创建好的segue对象 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // 1.拿到目标控制器 UIViewController *vc = segue.destinationViewController; // 2.设置目标控制器的标题 vc.title = [NSString stringWithFormat:@"%@ 的联系人列表", self.accountField.text]; } @end
联系人控制器中:
1.默认在UIBarButtonItem中仅仅能手动加入一左一右两个button,要向再加入button,须要代码实现
加入一个有点击事件的编辑button,通过[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editBtnClick)];
self.navigationItem.rightBarButtonItems = @[editBtn,addBtn];
2.使用UIActionSheet 设置左上角注销button。点击注销后。通过popViewController方法弹回到登录界面
3.因为在联系人界面会有两个跳转界面,所以须要推断segue的目标控制器
因为无论是手动还是自己主动类型的segue。在跳转前都会运行prepareForSegue方法,所以这个推断就能够在这种方法里写
通过获取到目标控制器对象vc,使用isKindOfClass推断,并各自设置代理
4.接下来就是运行各自的代理方法
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomaininMask,YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"];
[NSKeyedArchiver archiverRootObject:self.contacts toFile:path];
最后不要忘记刷新[self.tableView reloadData];
5.控件是通过xib或者storyboard创建出来的就会调用awakeFrmeNib方法,且仅仅调用一次
在这种方法中把UIView类型的切割线加入到self.contentView中,注意。不要直接将自控件加入到cell 中
6.当控件的frame被改动时会调用layoutSubviews方法,重写不论什么方法都要先[super layoutSubviews]
#import "NJContatcsViewController.h" #import "NJAddViewController.h" #import "NJContatc.h" #import "NJEditViewController.h" #import "NJContatcCell.h" #define NJContactsPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"] @interface NJContatcsViewController ()<UIActionSheetDelegate, NJAddViewControllerDelegate, NJEditViewControllerDelegate> /** * 点击注销button */ - (IBAction)logout:(UIBarButtonItem *)sender; /** * 保存全部用户数据 */ @property (nonatomic, strong) NSMutableArray *contatcs; @end @implementation NJContatcsViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 给当前控制器的当行控制器加入一个button UIBarButtonItem *addBtn = self.navigationItem.rightBarButtonItem; UIBarButtonItem *editBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editBtnClick)]; self.navigationItem.rightBarButtonItems = @[editBtn, addBtn]; } - (void)editBtnClick { // NSLog(@"editBtnClick"); // 开启tableview的编辑模式 // self.tableView.editing = !self.tableView.editing; [self.tableView setEditing:!self.tableView.editing animated:YES]; } - (IBAction)logout:(UIBarButtonItem *)sender { UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"确定要注销?" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:nil]; [sheet showInView:self.view]; } #pragma mark - UIActionSheetDelegate - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (0 != buttonIndex) return; // 移除栈顶控制器 [self.navigationController popViewControllerAnimated:YES]; } // 不管是手动类型的segue还是自己主动类型的segue, 在跳转之前都会运行该方法 // 控制器跳转之前(运行segue之前)运行 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // 0.推断目标控制器是加入还是编辑 // 1.取出目标控制器 UIViewController *vc = segue.destinationViewController; if ([vc isKindOfClass:[NJAddViewController class]]) { NJAddViewController *addVc = (NJAddViewController *)vc; // 2.设置代理 addVc.delegate = self; }else if ([vc isKindOfClass:[NJEditViewController class]]){ // 传递数据 NJEditViewController *editVc = (NJEditViewController *)vc; // 通过tableview获取被点击的行号 NSIndexPath *path = [self.tableView indexPathForSelectedRow]; // 取出被点击行的模型 NJContatc *c = self.contatcs[path.row]; NSLog(@"联系人列表 %p" , c); // 赋值模型 editVc.contatc = c; // 设置代理 editVc.delegate = self; } } #pragma mark - NJEditViewControllerDelegate - (void)editViewControllerDidClickSavBtn:(NJEditViewController *)editViewController contatc:(NJContatc *)cpmtatc { // 0.更新保存的数据 // NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"]; [NSKeyedArchiver archiveRootObject:self.contatcs toFile:NJContactsPath]; // 1.刷新表格 [self.tableView reloadData]; } #pragma mark - NJAddViewControllerDelegate - (void)addViewControllerDidAddBtn:(NJAddViewController *)editViewController contatc:(NJContatc *)contatc { // 1.保存数据到数组中 [self.contatcs addObject:contatc]; // 在这个地方保存用户加入的全部的联系人信息 // NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject ] stringByAppendingPathComponent:@"contacts.arc"]; [NSKeyedArchiver archiveRootObject:self.contatcs toFile:NJContactsPath]; // 2.刷新表格 [self.tableView reloadData]; } #pragma mark - 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.contatcs.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 1.创建cell NJContatcCell *cell = [NJContatcCell cellWithTableView:tableView]; // 2.设置模型 // 设置数据 NJContatc *c = self.contatcs[indexPath.row];//0 cell.contatc = c; // 2.返回cell return cell; } // 仅仅在在tableview的编辑模式下才有加入 // 仅仅要实现该方法, 手指在cell上面滑动的时候就自己主动实现了删除button // commitEditingStyle: 传入提交的编辑操作(删除/加入) // forRowAtIndexPath: 当前正在编辑的行 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { // NSLog(@"%d", indexPath.row); if (UITableViewCellEditingStyleDelete == editingStyle) { // 1.改动数据 [self.contatcs removeObjectAtIndex:indexPath.row]; // 2.刷新表格 // reloadData会又一次调用数据的全部方法,刷新全部的行 // [self.tableView reloadData]; // 该方法用于删除tableview上指定行的cell // 注意:使用该方法的时候,模型中删除的数据的条数必须和deleteRowsAtIndexPaths方法中删除的条数一致,否则会报错 // 简而言之,就删除的数据必须和删除的cell保持一致 [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop]; // 3.更新保存的文件 [NSKeyedArchiver archiveRootObject:self.contatcs toFile:NJContactsPath]; }else if (UITableViewCellEditingStyleInsert == editingStyle) { // 加入一条数据 // NSLog(@"加入一条数据"); // 1.改动数据 NJContatc *c = [[NJContatc alloc] init]; c.name = @"xff"; c.phoneNumber = @"123456"; // [self.contatcs addObject:c]; [self.contatcs insertObject:c atIndex:indexPath.row + 1]; // NJContatc *c1 = [[NJContatc alloc] init]; // c1.name = @"xzz"; // c1.phoneNumber = @"123456"; // [self.contatcs insertObject:c1 atIndex:indexPath.row + 2]; // 2.刷新表格 // [self.tableView reloadData]; NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]; // 注意点:数组中插入的条数必须和tableview界面上插入的cell条一致 // 否则程序会报错 [self.tableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationBottom]; } } // 用于告诉系统开启的编辑模式是什么模式 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { // NSLog(@"indexPath = %d", indexPath.row); // return UITableViewCellEditingStyleInsert; if (indexPath.row % 2 == 0) { return UITableViewCellEditingStyleInsert; }else { return UITableViewCellEditingStyleDelete; } } #pragma mark - 懒载入 - (NSMutableArray *)contatcs { if (_contatcs == nil) { // 1.获取路径 // NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"]; // 2.从文件里读取数组 _contatcs = [NSKeyedUnarchiver unarchiveObjectWithFile:NJContactsPath]; // 3.假设第一次启动没有文件,就创建一个空的数组用于保存数据 if (_contatcs == nil) { _contatcs = [NSMutableArray array]; } } return _contatcs; } @end
加入控制器:
#import "NJAddViewController.h" //#import "NJContatcsViewController.h" #import "NJContatc.h" @interface NJAddViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *phoneField; @property (weak, nonatomic) IBOutlet UIButton *addBtn; /** * 点击加入button */ - (IBAction)addBtnOnClick:(UIButton *)sender; @end @implementation NJAddViewController - (void)viewDidLoad { [super viewDidLoad]; // 监听文本输入框的改变 // 1.拿到通知中心 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 2.注冊监听 // 注意点: 一定要写上通知的公布者 [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField]; [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.phoneField]; } - (void)viewDidAppear:(BOOL)animated { // 3.主动召唤出键盘 [self.nameField becomeFirstResponder]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)textChange { self.addBtn.enabled = (self.nameField.text.length > 0 && self.phoneField.text.length > 0); } - (IBAction)addBtnOnClick:(UIButton *)sender { // 0. 移除栈顶控制器 [self.navigationController popViewControllerAnimated:YES]; // 1.获取用户输入的姓名和电话 NSString *name = self.nameField.text; NSString *phone = self.phoneField.text; NJContatc *c = [[NJContatc alloc] init]; c.name = name; c.phoneNumber = phone; // 2.传递数据给联系人列表 if ([self.delegate respondsToSelector:@selector(addViewControllerDidAddBtn: contatc:)]) { [self.delegate addViewControllerDidAddBtn:self contatc:c]; } } @end
编辑控制器:
#import "NJAddViewController.h" //#import "NJContatcsViewController.h" #import "NJContatc.h" @interface NJAddViewController () @property (weak, nonatomic) IBOutlet UITextField *nameField; @property (weak, nonatomic) IBOutlet UITextField *phoneField; @property (weak, nonatomic) IBOutlet UIButton *addBtn; /** * 点击加入button */ - (IBAction)addBtnOnClick:(UIButton *)sender; @end @implementation NJAddViewController - (void)viewDidLoad { [super viewDidLoad]; // 监听文本输入框的改变 // 1.拿到通知中心 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 2.注冊监听 // 注意点: 一定要写上通知的公布者 [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField]; [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.phoneField]; } - (void)viewDidAppear:(BOOL)animated { // 3.主动召唤出键盘 [self.nameField becomeFirstResponder]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)textChange { self.addBtn.enabled = (self.nameField.text.length > 0 && self.phoneField.text.length > 0); } - (IBAction)addBtnOnClick:(UIButton *)sender { // 0. 移除栈顶控制器 [self.navigationController popViewControllerAnimated:YES]; // 1.获取用户输入的姓名和电话 NSString *name = self.nameField.text; NSString *phone = self.phoneField.text; NJContatc *c = [[NJContatc alloc] init]; c.name = name; c.phoneNumber = phone; // 2.传递数据给联系人列表 if ([self.delegate respondsToSelector:@selector(addViewControllerDidAddBtn: contatc:)]) { [self.delegate addViewControllerDidAddBtn:self contatc:c]; } } @end