美文网首页
09、CoreData版的联系人列表

09、CoreData版的联系人列表

作者: 深爱久随i | 来源:发表于2017-01-20 10:40 被阅读0次

    咱们的这个联系人列表可以对通讯录中的人进行添加联系人操作,并且可以点击某个联系人,进入详情界面,对联系人的个人信息进行修改并保存,实现一个简单的联系人列表就可以啦!!!
    第一步、建一个工程并增加如下的几个类,

    屏幕快照 2017-01-20 上午10.21.52.png

    1、先创建一个实体类,并增加如下属性,起名为Contacts

    屏幕快照 2017-01-20 上午10.28.24.png

    2、在我们的主界面ViewController界面创建一个tableView

    #import "ViewController.h"
    #import "AddViewController.h"
    #import "CoreDataHandle.h"
    #import "NSString+ChineseToLatin.h"
    #import "Contacts.h"
    #import "CustomCell.h"
    #import "PersonalViewController.h"
    @interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
    @property (weak, nonatomic) IBOutlet UITableView *tabView;
    @property(nonatomic,strong)NSMutableDictionary* allSectionMDic;//所有的分区,该字典的key为分区标题,该字典的值为可变数组,可变数组的元素为联系人对象
    
    
    //@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    //
    //@property (weak, nonatomic) IBOutlet UILabel *phoneLabel;
    //@property (weak, nonatomic) IBOutlet UIImageView *headImg;
    
    @end
    
    @implementation ViewController
    
    -(NSMutableDictionary*)allSectionMDic{
        if (!_allSectionMDic) {
            _allSectionMDic=[[NSMutableDictionary alloc] init];
        }
        return _allSectionMDic;
    }
    
    #pragma mark-------tableView的代理方法
    //返回行数
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        //获取字典所有的值,allValuesArray中存储的是字典所有的值,字典的值为可变数组
        NSArray* allValuesArray=self.allSectionMDic.allValues;
        //取出其中一个分区
        NSArray* sectionArray=[allValuesArray objectAtIndex:section];
        return sectionArray.count;
    }
    // 返回行高
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        return 100;
    }
    //定义单元格
    -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        CustomCell* cell=[tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        //获取字典所有的值,allValuesArray中存储的是字典所有的值,字典的值为可变数组
        NSArray* allValuesArray=self.allSectionMDic.allValues;
        //取出其中一个分区
        NSArray* sectionArray=[allValuesArray objectAtIndex:indexPath.section];
        //取出联系人
        Contacts* contacts=sectionArray[indexPath.row];
        cell.headImg.image=[UIImage imageWithData:contacts.headImg];
        cell.nameLabel.text=contacts.name;
        cell.phoneLabel.text=contacts.phone;
        return cell;
    }
    //返回分区数
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return [self.allSectionMDic allKeys].count;
    }
    
    
    //返回分区标题
    -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
        return [self.allSectionMDic allKeys][section];
        
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.automaticallyAdjustsScrollViewInsets=NO;
        NSArray* array=[[CoreDataHandle sharedCoreDataHandle] queryWithEntityName:@"Contacts" predicate:nil sortByAttribute:nil ascending:YES];
        [self sectionWithContacts:array];
        [self.tabView reloadData];
        
    }
    
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        
        
        if ([segue.identifier isEqualToString:@"yf"]) {
            //传值
            CustomCell* cell=(CustomCell*)sender;
            NSIndexPath* path=[self.tabView indexPathForCell:cell];
            NSString* key=[self.allSectionMDic allKeys][path.section];
            NSArray* array=[self.allSectionMDic objectForKey:key];
            Contacts* contacts=array[path.row];
            PersonalViewController* personVC=[segue destinationViewController];
            personVC.block=^{
                //从coreData中获取所有的联系人
                CoreDataHandle* coreData=[CoreDataHandle sharedCoreDataHandle];
                NSArray* allContacts=[coreData queryWithEntityName:@"Contacts" predicate:nil sortByAttribute:nil ascending:YES];
                //将字典中的旧数据清空
                if (self.allSectionMDic.count) {
                    [self.allSectionMDic removeAllObjects];
                }
                //对获取的联系人按照首字母进行分区处理
                [self sectionWithContacts:allContacts];
                
                //刷新数据
                [self.tabView reloadData];
                
            };
            personVC.contacts=contacts;
         
        }else{
            
            //  在此方法中获取添加联系人的控制器,实现block
            UINavigationController* naVC=[segue destinationViewController];
            AddViewController* addVC=naVC.childViewControllers.firstObject;
            addVC.block=^{
                //从coreData中获取所有的联系人
                CoreDataHandle* coreData=[CoreDataHandle sharedCoreDataHandle];
                NSArray* allContacts=[coreData queryWithEntityName:@"Contacts" predicate:nil sortByAttribute:nil ascending:YES];
                //将字典中的旧数据清空
                if (self.allSectionMDic.count) {
                    [self.allSectionMDic removeAllObjects];
                }
                //对获取的联系人按照首字母进行分区处理
                [self sectionWithContacts:allContacts];
                
                //刷新数据
                [self.tabView reloadData];
           
            };
    
        }
        
    }
    
    //将联系人动态分区的方法
    -(void)sectionWithContacts:(NSArray*)allContacts{
        //保证有联系人
        if (allContacts && allContacts.count) {
            //遍历数组,对每个联系人进行分区
            for (Contacts* contacts in allContacts) {
                //得到联系人姓名的首字母,根据首字母进行下一步操作
                NSString* firstWords=[NSString chineseTransformLettersWihthSourceString:contacts.name];
                //一共有两种情况
                //第一种是有分区,直接添加;第二种是没有分区,先创建分区再添加。分区就是大字典中的可变数组
                NSMutableArray* sectionArray=self.allSectionMDic[firstWords];
                if (sectionArray) {
                    // 说明分区存在
                    [sectionArray addObject:contacts];
                }else{
                     // 说明分区不存在
                    sectionArray=[[NSMutableArray alloc] init];
                    [sectionArray addObject:contacts];
                    [self.allSectionMDic setObject:sectionArray forKey:firstWords];
                    
                }
                
            }
        }
       
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    
    

    3、建一个自定义的cell,继承UITableViewCell
    Custom.h中

    @property (weak, nonatomic) IBOutlet UIImageView *headImg;
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    @property (weak, nonatomic) IBOutlet UILabel *phoneLabel;
    

    Custom.m中

    @implementation CustomCell
    
    - (void)awakeFromNib {
        self.headImg.layer.masksToBounds=YES;
        self.headImg.layer.cornerRadius=40.0;
    
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
        [super setSelected:selected animated:animated];
    
        // Configure the view for the selected state
    }
    
    @end
    

    4、创建一个添加联系人界面,起名为AddViewController,在这里进行联系人的添加操作

    #import "AddViewController.h"
    #import "CoreDataHandle.h"
    @interface AddViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
    - (IBAction)returnBtn:(UIBarButtonItem *)sender;
    @property (weak, nonatomic) IBOutlet UIImageView *headImg;
    
    @property (weak, nonatomic) IBOutlet UITextField *nameTF;
    @property (weak, nonatomic) IBOutlet UITextField *sexTF;
    @property (weak, nonatomic) IBOutlet UITextField *ageTF;
    @property (weak, nonatomic) IBOutlet UITextField *phoneTF;
    - (IBAction)finishBtn:(UIBarButtonItem *)sender;
    
    - (IBAction)selecePhotoAction:(UITapGestureRecognizer *)sender;
    
    @end
    
    @implementation AddViewController
    
    
    - (IBAction)returnBtn:(UIBarButtonItem *)sender {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    //完成按钮的点击方法
    - (IBAction)finishBtn:(UIBarButtonItem *)sender {
        //当内容填充完整的时候要做的操作
        if ([self isNull]) {
            //将数据存储到CoreData中
            CoreDataHandle* coreDataHandle=[CoreDataHandle sharedCoreDataHandle];
            NSDictionary* contactDic=@{@"name":self.nameTF.text,@"age":@(self.ageTF.text.intValue),@"sex":self.sexTF.text,@"phone":self.phoneTF.text,@"headImg": UIImageJPEGRepresentation((self.headImg.image), 1.0)};
           
           BOOL isSuccess= [coreDataHandle addDataWithEntityName:@"Contacts" values:@[contactDic]];
            if (isSuccess) {
                //返回上级界面
                [self.navigationController dismissViewControllerAnimated:YES completion:nil];
               //通知上级界面刷新界面  block或者协议代理
                if (self.block) {
                    self.block();
                }
      
            }else{
                NSLog(@"保存数据失败");
            }
        }
    }
    //选择照片换头像的方法
    - (IBAction)selecePhotoAction:(UITapGestureRecognizer *)sender {
        UIImagePickerController* pc=[[UIImagePickerController alloc] init];
        pc.allowsEditing=YES;
        pc.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;
        pc.delegate=self;
        [self presentViewController:pc animated:YES completion:nil];
    }
    //照片选择器的代理方法
    //点击取消按钮会执行的代理方法
    -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
        [picker dismissViewControllerAnimated:YES completion:nil];
    }
    //当我们选择好照片,点击确定按钮会执行的代理方法
    //info:存储着我们的多媒体资源
    -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
        //获取图片资源
        UIImage* img=nil;
        if (picker.allowsEditing) {
            // 说明允许编辑图片
            img=[info objectForKey:UIImagePickerControllerEditedImage];
        }else{
            //说明图片不允许被编辑
            img=[info objectForKey:UIImagePickerControllerOriginalImage];
        }
        //将图片显示在imgView上
        self.headImg.image=img;
        //退出相册
        [picker dismissViewControllerAnimated:YES completion:nil];
    }
    
    //判断输入框是否有内容
    -(BOOL)isNull{
        BOOL result=YES;
        NSString* msg=@"";
        if (self.nameTF.text.length==0) {
            result=NO;
            msg=@"请输入姓名";
        }else if (self.sexTF.text.length==0){
            result=NO;
            msg=@"请输入性别";
        }else if (self.phoneTF.text.length==0){
            result=NO;
            msg=@"请输入手机号";
        }else if (self.ageTF.text.length==0){
            result=NO;
            msg=@"请输入年龄";
        }
        if (result) {
            return result;
        }
        [self alertWithMsg:msg];
        return result;
        
    }
    
    //警示框
    -(void)alertWithMsg:(NSString*)msg{
        
        UIAlertController* alertController=[UIAlertController alertControllerWithTitle:@"友情提示" message:msg preferredStyle:(UIAlertControllerStyleAlert)];
        UIAlertAction* action=[UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
           
        }];
        [alertController addAction:action];
        [self presentViewController:alertController animated:YES completion:nil];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.headImg.layer.masksToBounds=YES;
        self.headImg.layer.cornerRadius=50.0;
      
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        
    }
    
    
    
    @end
    
    

    5、在创建一个个人界面,起名为PersonalViewController,用来保存个人信息

    #import "PersonalViewController.h"
    #import "AppDelegate.h"
    @interface PersonalViewController ()
    
    
    
    - (IBAction)editAction:(UIBarButtonItem *)sender;
    
    @end
    
    @implementation PersonalViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.headImg.layer.masksToBounds=YES;
        self.headImg.layer.cornerRadius=50.0;
        self.nameTF.text=self.contacts.name;
        self.ageTF.text=[NSString stringWithFormat:@"%@",self.contacts.age];
        self.phoneTF.text=self.contacts.phone;
        self.sexTF.text=self.contacts.sex;
        self.headImg.image=[UIImage imageWithData:self.contacts.headImg];
        self.view.userInteractionEnabled=NO;
       
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    
    - (IBAction)editAction:(UIBarButtonItem *)sender {
        
        self.view.userInteractionEnabled=!self.view.userInteractionEnabled;
        sender.title=self.view.userInteractionEnabled?@"完成":@"编辑";
        //当编辑状态为NO的时候,说明点击了完成按钮,我们就对数据进行更改
        if (!self.view.userInteractionEnabled) {
            self.contacts.headImg=UIImageJPEGRepresentation(self.headImg.image, 1.0);
            self.contacts.name=self.nameTF.text;
            self.contacts.age=@(self.ageTF.text.intValue);
            self.contacts.sex=self.sexTF.text;
            self.contacts.phone=self.phoneTF.text;
            //同步操作
            AppDelegate* appdelegate=[UIApplication sharedApplication].delegate;
            [appdelegate saveContext];
            if (self.block) {
                self.block();
                //返回上级界面,上级界面刷新数据
                [self.navigationController popViewControllerAnimated:YES];
            }
           
        }
    }
    @end
    
    

    6、在这里我对CoreData进行了封装,直接用的,这些方法需要在.h中进行声明

    #import "CoreDataHandle.h"
    
    
    @interface CoreDataHandle ()
    
    @property(nonatomic,retain)AppDelegate* appDelegate;
    @property(nonatomic,retain)NSManagedObjectContext* context;
    
    @end
    
    @implementation CoreDataHandle
    +(CoreDataHandle*)sharedCoreDataHandle{
        static CoreDataHandle* coreDataHandle=nil;
        if (coreDataHandle==nil) {
            coreDataHandle=[[CoreDataHandle alloc] init];
        }
        return coreDataHandle;
        
    }
    
    //重写属性的getter方法
    -(AppDelegate*)appDelegate{
        
        return (AppDelegate*)[UIApplication sharedApplication].delegate;
    }
    
    -(NSManagedObjectContext*)context{
        return self.appDelegate.managedObjectContext;
    }
    
    //增加
    -(BOOL)addDataWithEntityName:(NSString*)entityName values:(NSArray<NSDictionary*>*)valuesArray{
        //将字符串转换为类名
    //    Class objectClass=NSClassFromString(entityName);
        //创建要插入的被管理者对象
        //因为当前是一个公用的coreData处理,所以此处的类型不能写死,用到了多态,父类指针指向子类对象
        for (NSDictionary* valueDic in valuesArray) {
            NSManagedObject* addData=[NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.context];
            //当我们父类指针指向子类对象的时候,就不能直接调用子类的属性为它赋值,这时候就需要用到KVC
            [addData setValuesForKeysWithDictionary:valueDic];
    
        }
           //同步操作
        BOOL isSuccess=[[self context] save:nil];
        if (isSuccess) {
            return YES;
            
        }else{
            NSLog(@"同步失败");
            return NO;
        }
        
    }
    
    //查询  带条件查询
    //第一个参数:要查询的实体名
    //第二个参数:查询条件  若为nil则查询全表
    //第三个参数:按照哪个属性排序  若为nil则不排序
    //第四个参数:如果排序  YES:升序  NO:降序
    -(NSArray*)queryWithEntityName:(NSString*)entityName
                         predicate:(NSString*)predicate
                         sortByAttribute:(NSString*)attributeName
                         ascending:(BOOL)ascending{
        //创建要查询的实体对象
        NSFetchRequest* req=[[NSFetchRequest alloc] initWithEntityName:entityName];
        //查询条件
        if (predicate) {
            NSPredicate* myPredicate=[NSPredicate predicateWithFormat:predicate];
            req.predicate=myPredicate;
        }
        //排序
        if (attributeName) {
            NSSortDescriptor* sort=[NSSortDescriptor sortDescriptorWithKey:attributeName ascending:ascending];
            req.sortDescriptors=@[sort];
        }
        //上下文执行查询操作
        NSArray* resultArray=[self.context executeFetchRequest:req error:nil];
        return resultArray;
        
    }
    
    //修改数据
    //第一个参数:要更改的实体名称
    //第二个参数:要被更改的被管理者的范围
    //第三个参数:最终要被改成的值
    -(BOOL)updataWithEntityName:(NSString*)entityName range:(NSString*)rangeString result:(NSDictionary*)resultDic{
        NSArray* resultArray=[self queryWithEntityName:entityName predicate:rangeString sortByAttribute:nil ascending:YES];
        //遍历上面数组,将负责条件的所有对象都进行更新
        for (NSManagedObject* object in resultArray) {
            //遍历字典,将对象中所需要更改的属性值都进行更新
            for (NSString* key in resultDic) {
                [object setValue:resultDic[key] forKey:key];
            }
        }
        //同步操作
       BOOL isSuccess= [[self context] save:nil];
        if (isSuccess) {
            return YES;
        }
        
        NSLog(@"更新失败");
        return NO;
        
    }
    
    //删除
    -(BOOL)removeObjectWithManageObjects:(NSArray<NSManagedObject*>*)manageObjects{
        for (NSManagedObject* item in manageObjects) {
            [self.context deleteObject:item];
        }
        
        //同步操作
        BOOL isSuccess= [[self context] save:nil];
        if (isSuccess) {
            return YES;
        }
        
        NSLog(@"更新失败");
        return NO;
    
    }
    
    
    
    @end
    

    7、这是一个将汉字转拼音的方法

    #import "NSString+ChineseToLatin.h"
    
    @implementation NSString (ChineseToLatin)
    //汉字转拼音
    +(NSString*)chineseTransformLettersWihthSourceString:(NSString*)sourceString{
        //将字符串中的空格替换掉
        [sourceString stringByReplacingOccurrencesOfString:@" " withString:@""];
        //    sourceString = nil;空对象
        //    sourceString = @"";对象的值为空字符串
        //说明字符串对象不为空
        if (sourceString && sourceString.length !=0) {
            NSMutableString* str = [NSMutableString stringWithString:sourceString];
            //将汉字转为字母
            //第一个参数:要转换的源字符串
            //第二个参数:要转换的范围 如果需要全部转换,此处填写NULL即可
            //第三个参数:转换的类型
            //第四个参数:  YES就是还是得到源字符串 NO得到的是转换好之后的。
            //带声调的拼
            //__bridge: 当转换类型的时候框架体系发生的改变,不让内存管理方式改变。那么久需要它来修饰类型
            CFStringTransform((__bridge CFMutableStringRef)str, NULL, kCFStringTransformToLatin, NO);
            NSLog(@"带声调的----%@",str);
            //去掉声调
            CFStringTransform((__bridge CFMutableStringRef)str, NULL, kCFStringTransformStripCombiningMarks, NO);
            NSLog(@"不带声调的----%@",str);
            //将拼音大写,截取首字母
            NSString* upString =  [str uppercaseString];
            upString = [upString substringToIndex:1];
            //
            NSLog(@"大写的首字母----%@",upString);
            return upString;
        }
        //当字符串不存在返回#
        return @"#";
    }
    @end
    
    

    这样简单的通讯录就完成了运行如下

    ![ ![屏幕快照 2017-01-20 上午10.39.21.png](https://img.haomeiwen.com/i2758407/a5bbbac67c52783e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)](https://img.haomeiwen.com/i2758407/2d7860e19f073c5f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    相关文章

      网友评论

          本文标题:09、CoreData版的联系人列表

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