美文网首页UI基础
iOS实战项目开发:通讯录

iOS实战项目开发:通讯录

作者: 952625a28d0d | 来源:发表于2016-03-21 19:40 被阅读241次
  • 页面跳转
  • MBProgressHUD第三方类库
  • 数据存储
  • UITableView深入理解
  • 代理(代理传值)

storyBoard实现页面跳转布局

Paste_Image.png
  • 删除系统的VC storyBoard中的xib 拖拽自己的xib并 添加导航控制器 item等等 最后创建VC进行关联
Paste_Image.png

实现输入框的监听

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

- (void)addobser{
    // 注册通知 添加观察者
    /*
     observer:给self添加 的意思是针对本控制器
     selector:调用的方法
     name:表示对哪一个属性观察
     object:表示要观察的对象
     */
    //    添加用户名输入框观察者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField];
    //    添加密码输入框观察者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.passwordField];
}```

pragma mark - 文本框变化后调用的方法

  • (void)textChange{
    // if (self.nameField.text.length && self.passwordField.text.length) {
    // self.loginBtn.enabled = YES;
    // }else{
    // self.loginBtn.enabled = NO;
    // }
    // 等价于 三目运算符
    self.loginBtn.enabled = (self.nameField.text.length && self.passwordField.text.length);
    }

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }```

效果:

login.gif

实现Segue的传值 和 跳转

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #78492a}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #008400}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #703daa}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3d1d81}span.s1 {font-variant-ligatures: no-common-ligatures}span.s2 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures}span.s3 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s4 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s5 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s6 {font-variant-ligatures: no-common-ligatures; color: #3d1d81}span.s7 {font-variant-ligatures: no-common-ligatures; color: #d12f1b}span.s8 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures; color: #d12f1b}span.s9 {font-variant-ligatures: no-common-ligatures; color: #4f8187}

#pragma mark - Navigation 跳转之前的准备工作
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    //1:取得目标控制器
    UIViewController *contactVC = segue.destinationViewController;
    // 2:设置标题(传值)
    contactVC.title = [NSString stringWithFormat:@"%@的联系人列表",self.nameField.text];
}

#pragma mark - 当用户点击之后 实现传值和跳转工作
- (IBAction)loginOnclick:(id)sender {
    // 执行跳转
    [self performSegueWithIdentifier:@"LoginToContact" sender:nil];
}```

效果

![segus.gif](http:https://img.haomeiwen.com/i189984/1597cea29f203b52.gif?imageMogr2/auto-orient/strip)

###UIAlertViewController与添加页面布局

  • (IBAction)exitAction:(id)sender {
    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"要注销吗" message:@"真的要注销吗?" preferredStyle:UIAlertControllerStyleActionSheet];
    // 添加取消按钮
    [alertC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    // 添加确定按钮
    [alertC addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
    [self.navigationController popViewControllerAnimated:NO];
    }]];
    // 弹出
    [self presentViewController:alertC animated:YES completion:nil];

}```

exit.gif

添加功能与传值

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #d12f1b}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #4f8187}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #bb2ca2}span.s1 {font-variant-ligatures: no-common-ligatures; color: #78492a}span.s2 {font-variant-ligatures: no-common-ligatures}span.s3 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s4 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s5 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s6 {font-variant-ligatures: no-common-ligatures; color: #4f8187}

#import <UIKit/UIKit.h>

@class AddTableViewController,ContactModel;

@protocol AddVCDelegate <NSObject>

@optional

- (void)addContact:(AddTableViewController *)addVC didAddContact:(ContactModel *)model;

@end

@interface AddTableViewController : UIViewController

@property (nonatomic, weak) id<AddVCDelegate> delegate;

@end```

import "AddTableViewController.h"

import "ContactModel.h"

@interface AddTableViewController ()
@property (weak, nonatomic) IBOutlet UITextField *phoneField;
@property (weak, nonatomic) IBOutlet UITextField *passwordField;
@property (weak, nonatomic) IBOutlet UIButton *addContactButton; // 添加联系人按钮

@end

@implementation AddTableViewController

  • (IBAction)backAction:(id)sender {
    }

  • (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;

    // 添加观察者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.phoneField];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.passwordField];
    }

  • (void)textChange{
    self.addContactButton.enabled = (self.phoneField.text.length && self.passwordField.text.length);
    }

pragma mark - 视图已经出现 让输入框成为第一响应者

  • (void)viewDidAppear:(BOOL)animated{
    [self.phoneField becomeFirstResponder];
    }

  • (IBAction)addAction {

    // 关闭当前控制器
    [self.navigationController popViewControllerAnimated:YES];
    // 代理传值
    if ([self.delegate respondsToSelector:@selector(addContact:didAddContact:)]) {
    ContactModel *contactModel = [[ContactModel alloc] init];
    contactModel.name = self.phoneField.text;
    contactModel.phone = self.passwordField.text;
    [self.delegate addContact:self didAddContact:contactModel];
    }
    }

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

@end```

联系人控制器 获取并刷新数据

  • 设置代理 遵守代理 实现代理方法 中 获取数据 刷新TableView 并存储数据
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #78492a}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #008400}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #703daa}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px 'Heiti SC Light'; color: #008400}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #4f8187}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3d1d81}span.s1 {font-variant-ligatures: no-common-ligatures}span.s2 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s3 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s4 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s5 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures}span.s6 {font: 18.0px Menlo; font-variant-ligatures: no-common-ligatures; color: #000000}span.s7 {font: 18.0px Menlo; font-variant-ligatures: no-common-ligatures}span.s8 {font-variant-ligatures: no-common-ligatures; color: #3d1d81}span.s9 {font-variant-ligatures: no-common-ligatures; color: #4f8187}span.s10 {font-variant-ligatures: no-common-ligatures; color: #008400}span.s11 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures; color: #008400}

#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    
    // 拿到目的控制器
    id vc = segue.destinationViewController;
    // 判断是哪一个控制器
    if ([vc isKindOfClass:[AddTableViewController class]]) {
        // 如果是跳转到添加联系人控制器 设置代理
        AddTableViewController *addVc = vc;
        addVc.delegate = self;
    }else if ([vc isKindOfClass:[EditTableViewController class]]){
        EditTableViewController *editVC = vc;
        // 取得选中的那一行
        NSIndexPath *path = [self.tableView indexPathForSelectedRow];
        // 数据传入
        editVC.contactModel = self.contactArr[path.row];
        // 设置代理
        editVC.delegate = self;
    }
    
    
    // 拿到控制器
//    AddTableViewController *addVC = segue.destinationViewController;
    // 设置代理
//    addVC.delegate = self;
}```

pragma mark - addContactDelegate

  • (void)addContact:(AddTableViewController *)addVC didAddContact:(ContactModel *)model{
    // 1:把传过来的数据模型给我们的数组
    [self.contactArr addObject:model];
    // 2:刷新表示图
    [self.tableView reloadData];
    // 3:对象归档
    [NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];
    }```
add.gif

数据归档存储

  • 用户名 密码 记住密码 用NSUserDefults存储

  • 编写key 存储于读取

// 数据存储
#define User_Name_Key @"name"
#define PWD_key @"password"
#define RemPwdKry @"rem_pwd"```

- 读取数据

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

    // 读取上次的配置
    NSUserDefaults *defults = [NSUserDefaults standardUserDefaults];
    self.nameField.text = [defults valueForKey:User_Name_Key];
    self.passwordField.text = [defults valueForKey:PWD_key];
    self.remberSwitch.on = [defults boolForKey:RemPwdKry];
    // 如果开关打开 密码框则自动存入数据
    if (self.remberSwitch.isOn) {
    self.passwordField.text = [defults valueForKey:PWD_key];
    self.loginBtn.enabled = YES;
    }

    // 监听输入框
    [self addobser];
    }```

  • 存储数据并同步数据

#pragma mark - 当用户点击之后 实现传值和跳转工作
- (IBAction)loginOnclick:(id)sender {
    if (![self.nameField.text isEqualToString:@"jafar"]) {
        [MBProgressHUD showError:@"账号不存在"];
        return;
    }
    if (![self.passwordField.text isEqualToString:@"jyf2015."]){
        [MBProgressHUD showError:@"密码错误"];
        return;
    }
    // 显示蒙版
    [MBProgressHUD showMessage:@"正在登录"];
    // 模拟两秒时间,结束跳转
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 移除遮盖
        [MBProgressHUD hideHUD];
        // 执行跳转
        [self performSegueWithIdentifier:@"LoginToContact" sender:nil];
    });
    
    // 存储用户名和密码
    NSUserDefaults *userDefult = [NSUserDefaults standardUserDefaults];
    [userDefult setValue:self.nameField.text forKey:User_Name_Key];
    [userDefult setValue:self.passwordField.text forKey:PWD_key];
    [userDefult setBool:self.remberSwitch.isOn forKey:RemPwdKry];
    [userDefult synchronize];   // 同步
}```

![save.gif](http:https://img.haomeiwen.com/i189984/4943bea5e80ec6d4.gif?imageMogr2/auto-orient/strip)


####数据模型的存储方式

- 归档  遵守归档协议 编写路径宏定义 存储  取出  展示  可以存储数组类型哦

import <Foundation/Foundation.h>

@interface ContactModel : NSObject<NSCoding>

@property(nonatomic, copy) NSString * name;
@property(nonatomic, copy) NSString * phone;

@end```

#import "ContactModel.h"

@implementation ContactModel

/*
 将某个对象写入文件是会调用
 在这个方法中说清楚哪些属性需要存储
 */
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.phone forKey:@"phone"];
}

/*
 解析对象的时候会调用这个方法
 需要解析哪些属性
 */

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.phone = [aDecoder decodeObjectForKey:@"phone"];
    }
    return self;
}
@end```


//路径

define ContactFilePath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.data"]```

  • 数组获取的时候先从本地来获取
@interface ContactTableViewController ()<AddVCDelegate,EditTVCDelegate>

@property (nonatomic, strong) NSMutableArray *contactArr;   // 联系人数组

@end

@implementation ContactTableViewController

#pragma mark - 懒加载
- (NSMutableArray *)contactArr{
    if (!_contactArr) {
        // 数据解码
        _contactArr = [NSKeyedUnarchiver unarchiveObjectWithFile:ContactFilePath];
        if (_contactArr == nil) {
            _contactArr = [NSMutableArray array];
        }
    }
    return _contactArr;
    
}```

- 存储 这里注意 不管是添加联系人还是编辑修改之后的数据都要重新归档

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #78492a}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px 'Heiti SC Light'; color: #008400}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #008400}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3d1d81}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px}span.s1 {font-variant-ligatures: no-common-ligatures}span.s2 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s3 {font-variant-ligatures: no-common-ligatures; color: #4f8187}span.s4 {font: 18.0px Menlo; font-variant-ligatures: no-common-ligatures; color: #000000}span.s5 {font: 18.0px Menlo; font-variant-ligatures: no-common-ligatures}span.s6 {font-variant-ligatures: no-common-ligatures; color: #3d1d81}span.s7 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s8 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures}span.s9 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s10 {font-variant-ligatures: no-common-ligatures; color: #78492a}

pragma mark - addContactDelegate

  • (void)addContact:(AddTableViewController *)addVC didAddContact:(ContactModel *)model{
    // 1:把传过来的数据模型给我们的数组
    [self.contactArr addObject:model];
    // 2:刷新表示图
    [self.tableView reloadData];
    // 3:对象归档
    [NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];
    }

pragma mark - editContactDelegate

  • (void)editVC:(EditTableViewController *)editVC contactModel:(ContactModel *)model{
    [self.tableView reloadData];
    [NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];
    }```
archive.gif

数据编辑方面的逻辑

  • 代理传值 编辑前后输入框enabled属性的判断 主控制器获取之后 刷新与存储逻辑
#import <UIKit/UIKit.h>

@class ContactModel,EditTableViewController;

@protocol EditTVCDelegate <NSObject>

@optional

- (void)editVC:(EditTableViewController *)editVC contactModel:(ContactModel *)model;

@end

@interface EditTableViewController : UIViewController

@property (nonatomic, strong) ContactModel *contactModel;

@property (nonatomic, weak) id<EditTVCDelegate> delegate;

@end```


pragma mark - 编辑按钮

  • (IBAction)editAction:(UIBarButtonItem *)sender {
    // 如果是编辑状态 结束编辑
    if (self.name.enabled) {
    self.name.enabled = NO;
    self.phone.enabled = NO;
    [self.view endEditing:YES];
    self.saveBtn.hidden = YES;
    sender.title = @"编辑";
    // 还原回原来的数据
    self.name.text = self.contactModel.name;
    self.phone.text = self.contactModel.phone;
    }else{
    self.name.enabled = YES;
    self.phone.enabled = YES;
    [self.view endEditing:YES];
    self.saveBtn.hidden = NO;
    sender.title = @"取消";
    }
    }

pragma mark - 保存按钮

  • (IBAction)save:(id)sender {
    // 保存 并且传递数据
    [self.navigationController popViewControllerAnimated:YES];
    if ([self.delegate respondsToSelector:@selector(editVC:contactModel:)]) {
    // 更新数据模型
    self.contactModel.name = self.name.text;
    self.contactModel.phone = self.phone.text;
    [self.delegate editVC:self contactModel:self.contactModel];
    }
    }

  • (void)viewDidLoad {
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;

    // 赋值
    self.name.text = self.contactModel.name;
    self.phone.text = self.contactModel.phone;

    // 文本框验证
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textCheck) name:UITextFieldTextDidChangeNotification object:self.name];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textCheck) name:UITextFieldTextDidChangeNotification object:self.phone];
    }

pragma mark - 文本验证后调用的方法

  • (void)textCheck{
    self.saveBtn.enabled = (self.name.text.length && self.phone.text.length);
    }

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

/*

pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation

  • (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    }
    */

@end```

主控制器的刷新

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #78492a}p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo}p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #3d1d81}p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; min-height: 21.0px}p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #008400}p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #703daa}p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px 'Heiti SC Light'; color: #008400}p.p8 {margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #4f8187}span.s1 {font-variant-ligatures: no-common-ligatures}span.s2 {font-variant-ligatures: no-common-ligatures; color: #bb2ca2}span.s3 {font-variant-ligatures: no-common-ligatures; color: #4f8187}span.s4 {font-variant-ligatures: no-common-ligatures; color: #000000}span.s5 {font-variant-ligatures: no-common-ligatures; color: #703daa}span.s6 {font-variant-ligatures: no-common-ligatures; color: #78492a}span.s7 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures}span.s8 {font: 18.0px Menlo; font-variant-ligatures: no-common-ligatures; color: #000000}span.s9 {font: 18.0px Menlo; font-variant-ligatures: no-common-ligatures}span.s10 {font-variant-ligatures: no-common-ligatures; color: #3d1d81}span.s11 {font-variant-ligatures: no-common-ligatures; color: #008400}span.s12 {font: 18.0px 'Heiti SC Light'; font-variant-ligatures: no-common-ligatures; color: #008400}

#pragma mark - editContactDelegate
- (void)editVC:(EditTableViewController *)editVC contactModel:(ContactModel *)model{
    [self.tableView reloadData];
    
    [NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];
}

#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    
    // 拿到目的控制器
    id vc = segue.destinationViewController;
    // 判断是哪一个控制器
    if ([vc isKindOfClass:[AddTableViewController class]]) {
        // 如果是跳转到添加联系人控制器 设置代理
        AddTableViewController *addVc = vc;
        addVc.delegate = self;
    }else if ([vc isKindOfClass:[EditTableViewController class]]){
        EditTableViewController *editVC = vc;
        // 取得选中的那一行
        NSIndexPath *path = [self.tableView indexPathForSelectedRow];
        // 数据传入
        editVC.contactModel = self.contactArr[path.row];
        // 设置代理
        editVC.delegate = self;
    }
    
    
    // 拿到控制器
//    AddTableViewController *addVC = segue.destinationViewController;
    // 设置代理
//    addVC.delegate = self;
}```


####删除逻辑  注意数据的更新 和 视图的更新

pragma mark - 调用代理 实现删除功能

  • (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
    // 删除数据模型
    [self.contactArr removeObjectAtIndex:indexPath.row];
    // 刷新视图
    [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
    // 归档
    [NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];
    }
    }```
delegate.gif

相关文章

网友评论

    本文标题:iOS实战项目开发:通讯录

    本文链接:https://www.haomeiwen.com/subject/fsyklttx.html