IOS开发教程第一季之02UI进阶day3合并IOS学习014--Segue通讯录案例

1.快捷添加rootViewController和navigateController

默认Main.storyboard中点选view图标,菜单Editor–Embed in–NavigateController了,将直接将rootViewController和navigateController一同创建
在这里插入图片描述

2.文本框的代理监听

界面:
在这里插入图片描述
指定控制器为LoginViewController类
LoginViewController.m

#import "LoginViewController.h"

@interface LoginViewController ()<UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];
  self.usernameField.delegate=self;
}
//点击的时候会调用一次
/*
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
  NSLog(@"%@",self.usernameField.text);
  return YES;
}
 */
//文本框已经开始编辑
/*
- (void)textFieldDidBeginEditing:(UITextField *)textField{
  NSLog(@"%@",self.usernameField.text);

}

//是否允许这个文本框结束编辑
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
  return NO;
}
  */
//文本框结束编辑
- (void)textFieldDidEndEditing:(UITextField *)textField{
  NSLog(@"文本框已经结束编辑");

}

//是否允许文本框改变文字内容,非实时监听文本改变
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
  NSLog(@"%@",self.usernameField.text);
  return YES;//YES文本可以改变,NO文本不能改变
}
@end

直接是用addtarget方式监听,不使用代理
LoginViewController.m

#import "LoginViewController.h"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];

  //监听文本框
  [self.usernameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.passwordField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
}

-(void)textChange{
  //如果两个文本框都有内容
  /*
  if (self.usernameField.text.length>0&&self.passwordField.text.length>0) {
    self.loginButton.enabled=YES;
  }else{
    //不都有值的时候,登录按钮不可用
    self.loginButton.enabled=NO;
  }
  */
  //或直接使用
  self.loginButton.enabled=self.usernameField.text.length>0&&self.passwordField.text.length>0;

}
@end
3.Segue的属性

segue是控制器之间的那根线
在这里插入图片描述
每个segue对象,都有三个属性
1、唯一标识符
@property(nonatomic,readonly)NSString* identifier;
2、来源控制器
@property(nonatomic,readonly)id sourceViewController;
3、目标控制器
@property(nonatomic,readonly)id destinationViewController;

segue分为量大类型
1、自动型:点击某个控件后,自动执行segue,自动完成界面跳转
直接拖拽按钮到下一个控制器中,选择show或push即可
2、手动型:需要通过写代码手动执行segue,才能完成界面跳转

恰当的时候,使用perform方法执行对应的segue
[self performSegueWithIdentifier:@“identifiername” sender:nil];

如果点击某个空间后,需要做一些判断,也就是说,满足一定条件后才跳转到下一个界面,建议使用手动型segue

#import "LoginViewController.h"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];

  //监听文本框
  [self.usernameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.passwordField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  
  [self.loginButton addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
}

-(void)login{
	//用户名和密码都正确的情况下
  if ([self.usernameField.text isEqualToString:@"1"] && [self.passwordField.text isEqualToString:@"1"]) {
    [self performSegueWithIdentifier:@"login2contacts" sender:nil];

    return;
  }
}
-(void)textChange{
  //如果两个文本框都有内容
  self.loginButton.enabled=self.usernameField.text.length>0&&self.passwordField.text.length>0;
}

@end
4.延时登录

如果需要等待几秒钟在执行操作可以使用dispatch_after

#import "LoginViewController.h"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];

  //监听文本框
  [self.usernameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.passwordField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  
  [self.loginButton addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
}

-(void)login{

  //延时执行,第二个参数延时的秒数
  dispatch_after(dispatch_time( DISPATCH_TIME_NOW,(int64_t)( 3*NSEC_PER_SEC)), dispatch_get_main_queue(),^{
    if ([self.usernameField.text isEqualToString:@"1"] && [self.passwordField.text isEqualToString:@"1"]) {
    [self performSegueWithIdentifier:@"login2contacts" sender:nil];
    }
  });
 
}
-(void)textChange{
  //如果两个文本框都有内容
  self.loginButton.enabled=self.usernameField.text.length>0&&self.passwordField.text.length>0;

}


@end
5.注销

创建另外一个类,指定为内容控制器的类
ContactViewController.m

#import "ContactViewController.h"

@interface ContactViewController ()

@end

@implementation ContactViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加左上角注销的按钮
  UIBarButtonItem* item=[[UIBarButtonItem alloc]initWithTitle:@"注销" style:UIBarButtonItemStylePlain target:self action:@selector(logout)];
  self.navigationItem.leftBarButtonItem=item;
}
//登出方法.注销按钮的点击事件,弹出一个对话框
-(void)logout{
  NSLog(@"注销按钮弹框");
  //被放弃的方法,不能够正常显示
  UIActionSheet* sheet=[[UIActionSheet alloc]initWithTitle:@"注销" delegate:nil cancelButtonTitle:@"取消按钮标题" destructiveButtonTitle:@"另一个选项标题" otherButtonTitles:nil, nil];
  [sheet showInView:self.view];
}

@end
6.ViewController之间传值

performSegueWithIdentifier:sender:方法的完整执行过程

[self performSegueWithIdentifier:@"login2contacts" sender:nil];

//这个self是来源控制器
1、根据identifier去storyboard中找到对应的线,新建UIStoryboardSegue对象。

  • 设置segue对象的sourceViewController(来源控制器)
  • 新建并设置Segue对象的destinationViewController(目标控制器)

2、调用sourcViewController下面的方法,做一些跳转前的准备工作并且传入创建好的Segue对象

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;

这个sender是当初performSegueWithIdentifier:sender中传入的sender

3、调用Segue对象的-(void)perform方法开始执行界面跳转操作

  • 去的sourViewController所在的UINavigationController
  • 调用UINavigationController的push方法将desionationViewController压入栈中,完成跳转

具体到下面的代码中
1、先找目标控制器ContactViewController,拿到目标控制器对象
2、给目标控制器设置一个username的属性
3、将用户名控件上的文本赋值给目标控制器的username属性
4、在目标控制器的viewDid方法或合适的位置获取self.username属性的值即可完成值在viewController之间的传递。

LoginViewController.m

#import "LoginViewController.h"
#import "ContactViewController.h"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];

  //监听文本框
  [self.usernameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.passwordField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  
  [self.loginButton addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
  
}

-(void)login{
  //使用第三方库
  //[MBProgressHUD showMessage:@"正在登录"];
  //[SVProgressHUD show];
  //延时执行,第二个参数延时的秒数
  dispatch_after(dispatch_time( DISPATCH_TIME_NOW,(int64_t)( 3*NSEC_PER_SEC)), dispatch_get_main_queue(),^{
    if ([self.usernameField.text isEqualToString:@"1"] && [self.passwordField.text isEqualToString:@"1"]) {
    [self performSegueWithIdentifier:@"login2contacts" sender:nil];
    }
  });
 
}
//-------------------------------------------------------------
//只要走storyboard线都会调用这个方法
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
  //获取目标控制器
  ContactViewController* contact= segue.destinationViewController;
  //将控件上的文本赋值到目标控制器的username属性上
  contact.username=self.usernameField.text;
  
}
//---------------------------------------------------------------

-(void)textChange{
  //如果两个文本框都有内容
  self.loginButton.enabled=self.usernameField.text.length>0&&self.passwordField.text.length>0;
}


@end

ContactViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface ContactViewController : UITableViewController
//设置一个username属性,用来接收从根控制器传来的用户名
@property(nonatomic,copy) NSString* username;


@end

NS_ASSUME_NONNULL_END

ContactViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加左上角注销的按钮
  UIBarButtonItem* item=[[UIBarButtonItem alloc]initWithTitle:@"注销" style:UIBarButtonItemStylePlain target:self action:@selector(logout)];
  self.navigationItem.leftBarButtonItem=item;
  
  //将来源控制器设定的username属性的值使用上
  self.navigationItem.title=self.username;
}

//登出方法.注销按钮的点击事件,弹出一个对话框
-(void)logout{
  NSLog(@"注销按钮弹框");
  //被放弃的方法,不能够正常显示
  UIActionSheet* sheet=[[UIActionSheet alloc]initWithTitle:@"注销" delegate:nil cancelButtonTitle:@"取消按钮标题" destructiveButtonTitle:@"另一个选项标题" otherButtonTitles:nil, nil];
  [sheet showInView:self.view];
}

@end
7.ViewController之间逆传值–添加联系人

1、创建联系人模型Contract
Contract.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Contract : NSObject
@property(nonatomic,copy)NSString* name;
@property(nonatomic,copy)NSString* number;
@end

NS_ASSUME_NONNULL_END

Contract.m

#import "Contract.h"

@implementation Contract

@end

2、创建联系人列表对应的ContractViewController
ContractViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
//设置一个username属性,用来接收从根控制器传来的用户名
@interface ContactViewController : UITableViewController
@property(nonatomic,copy) NSString* username;


@end

NS_ASSUME_NONNULL_END

ContractViewController.m

#import "ContactViewController.h"
#import "AddViewController.h"
@interface ContactViewController ()<AddViewControllerDelegate>
@property(nonatomic,strong)NSMutableArray* contracts;
@end

@implementation ContactViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加左上角注销的按钮
  UIBarButtonItem* item=[[UIBarButtonItem alloc]initWithTitle:@"注销" style:UIBarButtonItemStylePlain target:self action:@selector(logout)];
  self.navigationItem.leftBarButtonItem=item;
  
  //将来源控制器设定的username属性的值使用上
  self.navigationItem.title=self.username;
}

#pragma mark -----懒加载数据-----
//懒加载contracts
//重写contracts的get方法
-(NSMutableArray*)contracts{
  if (_contracts==nil) {
    _contracts=[NSMutableArray array];
    
  }
  
  return _contracts;
}
//实现tableView的数据源方法
//返回一组有多少行
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  return self.contracts.count;
}
//返回tableviewcell
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  //单元格重用id
  static NSString* strId=@"contractCell";
  //去缓存池找
  UITableViewCell* cell= [tableView dequeueReusableCellWithIdentifier:strId];
  
  //给单元格赋值
  cell.textLabel.text=[self.contracts[indexPath.row] name] ;
  cell.detailTextLabel.text=[self.contracts[indexPath.row] number];
  
  return cell;
}
//-----------------------------------------------------------------------
//实现代理的方法(逆传)
-(void)addViewController:(AddViewController *)addViewController withmodel:(Contract *)contract{
  //把模型数据传到contracts数组中
  [self.contracts addObject:contract];
  [self.tableView reloadData];
  NSLog(@"%@----%@",contract.name,contract.number);
}
//获取segue的方法,只有走storyboard线,无论是自动型还是手动型都会调用
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
  AddViewController* add=segue.destinationViewController;
  add.delegate=self;
}
//-----------------------------------------------------------------------

//登出方法.注销按钮的点击事件,弹出一个对话框
-(void)logout{
  NSLog(@"注销按钮弹框");
  //被放弃的方法,不能够正常显示
  UIActionSheet* sheet=[[UIActionSheet alloc]initWithTitle:@"注销" delegate:nil cancelButtonTitle:@"取消按钮标题" destructiveButtonTitle:@"另一个选项标题" otherButtonTitles:nil, nil];
  [sheet showInView:self.view];
}

@end

3、创建新的viewController并制定AddViewController作为控制器类
AddViewController.h

#import <UIKit/UIKit.h>
#import "Contract.h"
@class AddViewController;
NS_ASSUME_NONNULL_BEGIN
@protocol AddViewControllerDelegate <NSObject>
@optional
-(void)addViewController:(AddViewController*)addViewController withmodel:(Contract *) contract;
@end
@interface AddViewController : UIViewController
@property(nonatomic,weak)id<AddViewControllerDelegate> delegate;
@end
NS_ASSUME_NONNULL_END

AddViewController.m

#import "AddViewController.h"
#import "Contract.h"
@interface AddViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UITextField *numberField;
@property (weak, nonatomic) IBOutlet UIButton *addButton;

@end

@implementation AddViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 监听两个文本框的内容变化
  [self.nameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.numberField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  //监听添加按钮的点击事件
  [self.addButton addTarget:self action:@selector(addClick) forControlEvents:UIControlEventTouchUpInside];
}
//添加按钮提交的方法
-(void)addClick{
  //判断代理方法是否能够响应,
  if ([self.delegate respondsToSelector:@selector(addViewController:withmodel:)]) {
    //创建一个模型
    Contract* contract=[[Contract alloc]init];
    contract.name=self.nameField.text;
    contract.number=self.numberField.text;
      //如果可以响应,则执行代理方法
    [self.delegate addViewController:self withmodel:contract];
  }
  
  //返回上一个控制器(联系人列表)
  [self.navigationController popViewControllerAnimated:YES];
}
//文本变动时的方法
-(void)textChange{
  self.addButton.enabled=self.nameField.text.length>0 && self.numberField.text>0;
}

@end

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.查看/编辑联系人

1、先从联系人列表里顺传值到–查看编辑联系人,因此需要在联系人列表里创建名字和号码属性。
2、创建EditingViewController类,并指导到新创建的控制器上
在这里插入图片描述

#import "EditViewController.h"

@interface EditViewController ()
- (IBAction)editClick:(UIBarButtonItem*)sender;
@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UITextField *numberField;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *saveitemButton;
@property (weak, nonatomic) IBOutlet UIButton *saveButton;

@end

@implementation EditViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

//右上角编辑按钮点击事件
- (IBAction)editClick:(UIBarButtonItem*)sender {
  if ([sender.title isEqualToString:@"编辑"]) {
    sender.title=@"取消";
    self.nameField.enabled=YES;
    self.numberField.enabled=YES;
    self.saveButton.hidden=NO;
  }else{
    sender.title=@"编辑";
    self.nameField.enabled=NO;
    self.numberField.enabled=NO;
    self.saveButton.hidden=YES;
  } 
}
@end
9.编辑保存联系人

修改的EditViewController控制器
EditViewController.h

#import <UIKit/UIKit.h>
#import "Contract.h"
@class EditViewController;
NS_ASSUME_NONNULL_BEGIN
@protocol EditViewControllerDelegate<NSObject>

-(void)editViewController:(EditViewController *)editViewController withcontract:(Contract*)contract;

@end
@interface EditViewController : UIViewController
@property(nonatomic,strong)Contract* contact;
@property(nonatomic,weak)id<EditViewControllerDelegate> delegate;
@end

NS_ASSUME_NONNULL_END

EditViewController.m

#import "EditViewController.h"

@interface EditViewController ()
- (IBAction)editClick:(UIBarButtonItem*)sender;
@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UITextField *numberField;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *saveitemButton;
@property (weak, nonatomic) IBOutlet UIButton *saveButton;

@end

@implementation EditViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //设置初始的文本框的内容(传过来的内容)
  self.nameField.text=self.contact.name;
  self.numberField.text=self.contact.number;
  
  //监听保存按钮的点击事件
  [self.saveButton addTarget:self action:@selector(saveButtonClick) forControlEvents:UIControlEventTouchUpInside];
}
//保存按钮被点击
-(void)saveButtonClick{
  
   Contract* con=[[Contract alloc]init];//实际这个模型用不上
  /*
      con.name=self.nameField.text;
      con.number=self.numberField.text;
  */
  
  self.contact.name=self.nameField.text;
  self.contact.number=self.numberField.text;
  //判断代理方法是不是可以响应
  if ([self.delegate respondsToSelector:@selector(editViewController:withcontract:)] ){
   
    [self.delegate editViewController:self withcontract:con];
  }
  
  //返回到上一个页面
  [self.navigationController popViewControllerAnimated:YES];
  
  
}

//右上角编辑按钮点击事件
- (IBAction)editClick:(UIBarButtonItem*)sender {
  if ([sender.title isEqualToString:@"编辑"]) {//点击编辑
    sender.title=@"取消";
    self.nameField.enabled=YES;
    self.numberField.enabled=YES;
    self.saveButton.hidden=NO;
  }else{
    sender.title=@"编辑";//点击取消
    self.nameField.enabled=NO;
    self.numberField.enabled=NO;
    self.saveButton.hidden=YES;
    
    //恢复到从tableview中传过来的模型的数据
    self.nameField.text=self.contact.name;
    self.numberField.text=self.contact.number;
  }
  
  
}
@end

AddViewController类
AddViewController.h

#import <UIKit/UIKit.h>
#import "Contract.h"
@class AddViewController;
NS_ASSUME_NONNULL_BEGIN
@protocol AddViewControllerDelegate <NSObject>

@optional
-(void)addViewController:(AddViewController*)addViewController withmodel:(Contract *) contract;


@end
@interface AddViewController : UIViewController
@property(nonatomic,weak)id<AddViewControllerDelegate> delegate;
@end

NS_ASSUME_NONNULL_END

AddViewController.m

#import "AddViewController.h"
#import "Contract.h"
@interface AddViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UITextField *numberField;
@property (weak, nonatomic) IBOutlet UIButton *addButton;

@end

@implementation AddViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 监听两个文本框的内容变化
  [self.nameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.numberField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  //监听添加按钮的点击事件
  [self.addButton addTarget:self action:@selector(addClick) forControlEvents:UIControlEventTouchUpInside];
}
//添加按钮提交的方法
-(void)addClick{
  //判断代理方法是否能够响应,
  if ([self.delegate respondsToSelector:@selector(addViewController:withmodel:)]) {
    //创建一个模型
    Contract* contract=[[Contract alloc]init];
    contract.name=self.nameField.text;
    contract.number=self.numberField.text;
      //如果可以响应,则执行代理方法
    [self.delegate addViewController:self withmodel:contract];
  }
  
  //返回上一个控制器(联系人列表)
  [self.navigationController popViewControllerAnimated:YES];
}
//文本变动时的方法
-(void)textChange{
  self.addButton.enabled=self.nameField.text.length>0 && self.numberField.text>0;
}

@end

ContactViewController类
ContactViewController.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN
//设置一个username属性,用来接收从根控制器传来的用户名
@interface ContactViewController : UITableViewController
@property(nonatomic,copy) NSString* username;


@end

NS_ASSUME_NONNULL_END

ContactViewController.m

#import "ContactViewController.h"
#import "AddViewController.h"
#import "EditViewController.h"
@interface ContactViewController ()<AddViewControllerDelegate,EditViewControllerDelegate>
@property(nonatomic,strong)NSMutableArray* contracts;
@end

@implementation ContactViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加左上角注销的按钮
  UIBarButtonItem* item=[[UIBarButtonItem alloc]initWithTitle:@"注销" style:UIBarButtonItemStylePlain target:self action:@selector(logout)];
  self.navigationItem.leftBarButtonItem=item;
  
  //将来源控制器设定的username属性的值使用上
  self.navigationItem.title=self.username;
}

#pragma mark -----懒加载数据-----
//懒加载contracts
//重写contracts的get方法
-(NSMutableArray*)contracts{
  if (_contracts==nil) {
    _contracts=[NSMutableArray array];
    
  }
  
  return _contracts;
}
//实现tableView的数据源方法
//返回一组有多少行
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  return self.contracts.count;
}
//返回tableviewcell
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  //单元格重用id
  static NSString* strId=@"contractCell";
  //去缓存池找
  UITableViewCell* cell= [tableView dequeueReusableCellWithIdentifier:strId];
  
  //给单元格赋值
  cell.textLabel.text=[self.contracts[indexPath.row] name] ;
  cell.detailTextLabel.text=[self.contracts[indexPath.row] number];
  
  return cell;
}
//-----------------------------------------------------------------------
//实现添加联系人的代理方法(逆传)
-(void)addViewController:(AddViewController *)addViewController withmodel:(Contract *)contract{
  //把模型数据传到contracts数组中
  [self.contracts addObject:contract];
  [self.tableView reloadData];
  NSLog(@"%@----%@",contract.name,contract.number);
}

//编辑联系人的代理方法
-(void)editViewController:(EditViewController *)editViewController withcontract:(Contract *)contract{
  [self.tableView reloadData];
  //NSLog(@"%@",contract.number);
}

//获取segue的方法,只有走storyboard线,无论是自动型还是手动型都会调用
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
  //先拿到一个viewcontroller
  UIViewController* viewController=segue.destinationViewController;
  //判断目标控制器的真实类型
  if ([viewController isKindOfClass:[AddViewController class]]) {
    //设置代理,需要强转一下
    AddViewController* add=(AddViewController*)viewController;
    add.delegate=self;

  }else{
    //顺传赋值
    EditViewController* edit=(EditViewController*)viewController;
    //设置代理
    edit.delegate=self;
    //获取点击cell的位置
    NSIndexPath* path= [self.tableView indexPathForSelectedRow];
    //获取模型
    Contract* con=self.contracts[path.row];
    edit.contact=con;
  }
}


//-----------------------------------------------------------------------

//登出方法.注销按钮的点击事件,弹出一个对话框
-(void)logout{
  NSLog(@"注销按钮弹框");
  //被放弃的方法,不能够正常显示
  UIActionSheet* sheet=[[UIActionSheet alloc]initWithTitle:@"注销" delegate:nil cancelButtonTitle:@"取消按钮标题" destructiveButtonTitle:@"另一个选项标题" otherButtonTitles:nil, nil];
  [sheet showInView:self.view];
}

@end

结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

10.开关处理

LoginViewController.m

//监听开关变化
- (IBAction)autoChangeClick:(UISwitch*)sender {
  if (sender.isOn) {
    //自动登录点开,则记住密码也点开
    //self.remPassword.on=YES;
    //用设置动画的形式打开
    [self.remPassword setOn:YES animated:YES];
  }
}

- (IBAction)remPasswordChange:(UISwitch*)sender {
  if (!sender.isOn) {
    //取消记住密码也不在进行自动登录
    //self.autoLogin.on=NO;
    [self.autoLogin setOn:NO animated:YES];

  }
}
11.记住密码和自动登录

LoginViewController.m

#import "LoginViewController.h"
#import "ContactViewController.h"
#define kUsernameKey @"kUsernameKey"
#define kPasswrodKey @"kPasswordKey"
#define kremPasswordKey @"kRemPassworKey"
#define kAutolgoinKey @"kAutologinKey"

@interface LoginViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *loginButton;
@property (weak, nonatomic) IBOutlet UISwitch *remPassword;
@property (weak, nonatomic) IBOutlet UISwitch *autoLogin;


- (IBAction)remPasswordChange:(UISwitch*)sender;
- (IBAction)autoChangeClick:(UISwitch*)sender;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];

  //监听文本框
  [self.usernameField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  [self.passwordField addTarget:self action:@selector(textChange) forControlEvents:UIControlEventEditingChanged];
  //监听登录文本
  [self.loginButton addTarget:self action:@selector(login) forControlEvents:UIControlEventTouchUpInside];
  //恢复开关状态
  NSUserDefaults* userdefaults=[NSUserDefaults standardUserDefaults];
  self.remPassword.on=[userdefaults boolForKey:kremPasswordKey];
  self.autoLogin.on=[userdefaults boolForKey:kAutolgoinKey];
  
  //恢复用户名和密码
  self.usernameField.text=[userdefaults objectForKey:kUsernameKey];
  //如果记住密码打开
  if (self.remPassword.isOn) {
    //将密码从usrdefaults中取出
    self.passwordField.text=[userdefaults objectForKey:kPasswrodKey];
  }
  //如果自动登录打开
  if (self.autoLogin.isOn) {
    [self login];//直接执行登录
  }
  
  

  [self textChange];
  
  
}

-(void)login{
  //使用第三方库
  //[MBProgressHUD showMessage:@"正在登录"];
  //[SVProgressHUD show];
  //延时执行,第二个参数延时的秒数
  //当用户名和密码正确的时候,进行跳转
  dispatch_after(dispatch_time( DISPATCH_TIME_NOW,(int64_t)( 3*NSEC_PER_SEC)), dispatch_get_main_queue(),^{
    if ([self.usernameField.text isEqualToString:@"1"] && [self.passwordField.text isEqualToString:@"1"]) {
    [self performSegueWithIdentifier:@"login2contacts" sender:nil];
      
      //保存状态
      NSUserDefaults* userdefaults=[NSUserDefaults standardUserDefaults];
      //写入到nsuerdefaults对象
      [userdefaults setBool:self.remPassword.isOn forKey:kremPasswordKey];//记住密码
      [userdefaults setBool:self forKey:kAutolgoinKey];//自动登录
      
      [userdefaults setObject:self.usernameField.text forKey:kUsernameKey];//用户名
      [userdefaults setObject:self.passwordField.text forKey:kPasswrodKey];//密码
      
      [userdefaults synchronize];//同步写入
    }
  });
 
}

//只要走storyboard线都会调用这个方法
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
  //获取目标控制器
  ContactViewController* contact= segue.destinationViewController;
  //将控件上的文本赋值到目标控制器的username属性上
  contact.username=self.usernameField.text;
  
}
-(void)textChange{
  //如果两个文本框都有内容
  self.loginButton.enabled=self.usernameField.text.length>0&&self.passwordField.text.length>0;

}

//监听开关变化
- (IBAction)autoChangeClick:(UISwitch*)sender {
  if (sender.isOn) {
    //自动登录点开,则记住密码也点开
    //self.remPassword.on=YES;
    //用设置动画的形式打开
    [self.remPassword setOn:YES animated:YES];
  }
}

- (IBAction)remPasswordChange:(UISwitch*)sender {
  if (!sender.isOn) {
    //取消记住密码也不在进行自动登录
    //self.autoLogin.on=NO;
    [self.autoLogin setOn:NO animated:YES];

  }
}
@end

效果
在这里插入图片描述

12.保存联系人(使用归档/解档)及滑动删除

由于[NSKeyedArchiver archiveRootObject:self.contracts toFile:kfilePath]方法已经过时,单独使用时还不出现问题,但是放在整个程序中,会出现崩溃的现象,这一点确实有点令人崩溃。
//让tableview进入编辑模式,里面的内容是点击(类似于点击,滑动后点击上面的按钮)之后所执行的操作
滑动删除

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
  //删除数组中的元素
  //[self.contracts removeObject:self.contracts[indexPath.row]];
  [self.contracts removeObjectAtIndex:indexPath.row];
  //刷新数据
  //[self.tableView reloadData];
  //删除某一行
  [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}

在这里插入图片描述
完整案例再次,代码不是太完美,有些功能实现的并不是很好
代码点击链接
自己写的笔记代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值