Fork me on GitHub

UI第十二讲 通讯录实战

//以下为通讯录完整代码,另附有构建框架,综合性较强,望多加练习!

ListViewController.m文件内容如下:

#import "LIstViewController.h"
#import "DetailViewController.h"
#import "ListTableViewCell.h"

@interface LIstViewController ()<UITableViewDataSource,UITableViewDelegate,DetailVCDelegate>

@property(nonatomic,strong)UITableView *tableView;
@property(nonatomic,strong)NSMutableArray *dataArray;

@end

@implementation LIstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [self loadTableView];
    
    //数组只有初始化后才能使用**************
    self.dataArray = [NSMutableArray array];

    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(rightBarButtonClick:)];
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(leftBarButtonClick:)];
    
    
    
    
}



//按钮点击事件以及按钮添加删除功能的实现--------------------------------------------------
-(void)rightBarButtonClick:(UIBarButtonItem *)bar
{

    [self.tableView setEditing:!self.tableView.isEditing animated:YES];

}

-(void)leftBarButtonClick:(UIBarButtonItem *)bar
{
    DetailViewController *detailVC = [[DetailViewController alloc]init];
    
    //数据传入第一个界面的代理
    detailVC.delegate = self;
    
    
    [self.navigationController pushViewController:detailVC animated:YES];
}

//代理方法的实现
-(void)passValueDelegate:(AddressBookModel *)passModel
{
     //代理方法传过来的值添加到数组中
    [self.dataArray addObject:passModel];
    //刷新tableView
    [self.tableView reloadData];

}

// 设置哪个cell可以编辑
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return self;
}
//真正的执行编辑的事情
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    //在编辑时,以一定要先处理好数据源,然后再处理view
    [self.dataArray removeObjectAtIndex:indexPath.row];
    //tableView 删除一个cell的方法,第一个参数代表 删除哪个分区的cell 第二个参数代表 删除时的动画
    [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];


}

//点击cell,返回第二个界面进行信息的修改
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *detailVC = [[DetailViewController alloc] init];
   //属性赋值第二步 把dataArray赋值给属性传值的对象
    detailVC.model = self.dataArray[indexPath.row];
    
    //修改值的代理
    detailVC.delegate = self;
    //传递indexPath.row的作用是再传回来,作为代理方法中的参数使用
    detailVC.index = indexPath.row;
    
    [self.navigationController pushViewController:detailVC animated:YES];
}
//修改值的代理方法
-(void)changeValueToListVC:(AddressBookModel *)passModel index:(NSInteger)index
{
    //替换数组 index位置的元素 为新的model
    [self.dataArray replaceObjectAtIndex:index withObject:passModel];
    // 刷新tableView
    [self.tableView reloadData];
  
}



//tableView的基本设置------------------------------------
-(void)loadTableView
{
    self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
    
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataArray.count;
}

-(ListTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    
    static NSString *str = @"CELL";
    ListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str];
    if (cell == nil) {
        cell = [[ListTableViewCell alloc
                 ]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:str];
        
    }
    //这里用model接收数据******************
    cell.model = self.dataArray[indexPath.row];
    return cell;
}

//cell的总高以及自适应高度-----------------------------------

//自适应高度  获取文本方法    此方法需要重新调用  *******************************
-(CGFloat)stringHeightWithString:(NSString *)str fontSize:(CGFloat)fontSize  contentSize:(CGSize)size
{
    //第一个参数,代表最大的范围
    //第二个参数 代表是否考虑字体和字号
    //第三个参数 代表是使用什么字体和字号
    //第四个参数  用不到  基本上是 nil
    CGRect  stringRect = [str boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} context:nil];
    NSLog(@"cgrect ==== %f", stringRect.size.height);
    return stringRect.size.height;
}
//cell总高计算
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    AddressBookModel *model = self.dataArray[indexPath.row];
    return 150 + [self stringHeightWithString:model.content fontSize:18 contentSize:CGSizeMake(self.view.frame.size.width - 20, 10000)];

}

 

 ListTableViewCell.m文件

 


#import "ListTableViewCell.h"

@interface ListTableViewCell ()

@property(nonatomic,strong)UILabel *nameLable;
@property(nonatomic,strong)UILabel *ageLable;
@property(nonatomic,strong)UILabel *sexLable;
@property(nonatomic,strong)UILabel *phoneLable;
@property(nonatomic,strong)UILabel *contentLable;


@property(nonatomic,strong)UIImageView *heardImageView;

@end



@implementation ListTableViewCell

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:(NSString *)reuseIdentifier];
    if (self) {
        self.nameLable = [[UILabel alloc] init];
        [self.contentView addSubview:self.nameLable];
        
        
        self.ageLable = [[UILabel alloc] init];
        [self.contentView addSubview:self.ageLable];
        
        self.sexLable = [[UILabel alloc] init];
        [self.contentView addSubview:self.sexLable];
        
        self.phoneLable = [[UILabel alloc] init];
        [self.contentView addSubview:self.phoneLable];
        
        self.contentLable= [[UILabel alloc] init];
        [self.contentView addSubview:self.contentLable];
        
        self.heardImageView = [[UIImageView alloc] init];
        [self.contentView addSubview:self.heardImageView];
        
        
        
    }

    return self;

}

//在这里面写所有的控件布局
-(void)layoutSubviews
{
    [super layoutSubviews];
    self.heardImageView.frame = CGRectMake(10, 10, 100, 100);
    
    self.nameLable.frame = CGRectMake(120, 10, self.frame.size.width - 130, 20);
    self.ageLable.frame = CGRectMake(120, 40, self.frame.size.width - 130, 20);
    self.sexLable.frame = CGRectMake(120, 70, self.frame.size.width - 130, 20);
    self.phoneLable.frame = CGRectMake(120, 90, self.frame.size.width - 130, 20);
    self.contentLable.frame = CGRectMake(10, 120, self.frame.size.width - 20, 20);
    
    self.contentLable.numberOfLines = 0;
    [self.contentLable sizeToFit];

}

//重写model的setter方法  将model接收到的值,赋给本身的lable*********************
-(void)setModel:(AddressBookModel *)model
{
    self.nameLable.text = model.name;
    self.ageLable.text = model.age;
    self.sexLable.text = model.sex;
    self.phoneLable.text = model.phone;
    self.contentLable.text = model.content;
    // 把NSData转换成image类型 ****
    self.heardImageView.image = [UIImage imageWithData:model.image];


}


@end

 

 DetailViewController.h文件

 


#import <UIKit/UIKit.h>
#import "AddressBookModel.h"

@protocol DetailVCDelegate <NSObject>

//传值的代理方法
-(void)passValueDelegate:(AddressBookModel *)passModel;
//修改的代理方法
-(void)changeValueToListVC:(AddressBookModel *)passModel index:(NSInteger)index;

@end



@interface DetailViewController : UIViewController



//代理传值的属性1
@property(nonatomic,assign)id<DetailVCDelegate>delegate;

//属性传值
@property(nonatomic,strong)AddressBookModel *model;

//代理传值的属性2
@property(nonatomic,assign)NSInteger index;


@end

 

DetailViewController.m文件

 


#import "DetailViewController.h"
#import "LTView.h"

@interface DetailViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate,UIActionSheetDelegate>

@property(nonatomic,strong)LTView *nameView;
@property(nonatomic,strong)LTView *sexView;
@property(nonatomic,strong)LTView *ageView;
@property(nonatomic,strong)LTView *phoneView;
//文本视图
@property(nonatomic,strong)UITextView *contentView;

@property(nonatomic,strong)UIButton *imageButton;
//设置照片属性
@property(nonatomic,strong)NSData *imageDate;


@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [self loadLTView];
    
    self.navigationController.navigationBar.translucent = NO;
    
    
}

//注意起名字时不能和系统名冲突
//初始化view
-(void)loadLTView
{
    //照片按钮的设置
    self.imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.imageButton setTitle:@"选取照片" forState:UIControlStateNormal];
    self.imageButton.backgroundColor = [UIColor grayColor];
    self.imageButton.frame = CGRectMake(self.view.frame.size.width/2 - 50 , 10, 100, 100);
    [self.imageButton addTarget:self action:@selector(imagePickerButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.imageButton];
    // 把前一页面传入的NSData类型的数据转换成image ***
    [self.imageButton setImage:[UIImage imageWithData:self.model.image] forState:UIControlStateNormal];
    
    //这里要保证,在修改时把图片从第一个页面保存到第二个页面,同时能够保存图片*********
    self.imageDate = self.model.image; self.nameView
= [[LTView alloc] initWithFrame:CGRectMake(10, 110, self.view.frame.size.width - 20, 30)]; self.nameView.nameLable.text = @"姓名"; //属性传值中的赋值 self.nameView.messageTextField.text = self.model.name; self.nameView.messageTextField.placeholder = @"请输入姓名"; [self.view addSubview:self.nameView]; self.ageView = [[LTView alloc] initWithFrame:CGRectMake(10, 150, self.view.frame.size.width - 20, 30)]; self.ageView.nameLable.text = @"年龄"; self.ageView.messageTextField.text = self.model.age; self.ageView.messageTextField.placeholder = @"请输入年龄"; [self.view addSubview:self.ageView]; self.sexView = [[LTView alloc] initWithFrame:CGRectMake(10, 190, self.view.frame.size.width - 20, 30)]; self.sexView.nameLable.text = @"性别"; //属性传值中的赋值 self.sexView.messageTextField.text = self.model.sex ; self.sexView.messageTextField.placeholder = @"请输入性别"; [self.view addSubview:self.sexView]; self.phoneView = [[LTView alloc] initWithFrame:CGRectMake(10, 230, self.view.frame.size.width - 20, 30)]; self.phoneView.nameLable.text = @"手机"; //属性传值中的赋值 self.phoneView.messageTextField.text = self.model.phone; self.phoneView.messageTextField.placeholder = @"请输入手机号"; [self.view addSubview:self.phoneView]; self.contentView = [[UITextView alloc] initWithFrame:CGRectMake(10, 270, self.view.frame.size.width -20, 150)]; //属性传值中的赋值 self.contentView.text = self.model.content; self.contentView.backgroundColor = [UIColor orangeColor]; [self.view addSubview:self.contentView]; UIButton *saveButton = [UIButton buttonWithType:UIButtonTypeCustom]; saveButton.frame = CGRectMake(10, 430, self.view.frame.size.width - 20, 30); [saveButton setTitle:@"保存" forState:UIControlStateNormal]; saveButton.backgroundColor = [UIColor greenColor]; //设置按钮圆角 saveButton.layer.borderWidth = 3.0f; //按钮点击事件 [saveButton addTarget:self action:@selector(saveButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:saveButton]; } //按钮点击事件 -(void)saveButtonClicked:(UIButton *)sender { //获取到所有可输入控件上的输入的数据 NSString *nameStr = self.nameView.messageTextField.text; NSString *ageStr = self.ageView.messageTextField.text; NSString *sexStr = self.sexView.messageTextField.text; NSString *phoneStr = self.phoneView.messageTextField.text; NSString *contentStr = self.contentView.text; //初始化一个model 传输照片时,要注意这里的格式*** AddressBookModel *model = [[AddressBookModel alloc] initWithName:nameStr age:ageStr sex:sexStr pnone:phoneStr content:contentStr image:self.imageDate]; // 判断代理人是否存在,代理人是否注册了passValueDelegate 和 if (self.delegate && [self.delegate respondsToSelector:@selector(passValueDelegate:)] && [self.delegate respondsToSelector:@selector(changeValueToListVC:index:)]) { // 如果self.model是否存在,如果存在 则判定为是修改联系人,所以 触发changeValueToListVC:index:方法 if (self.model != nil) { // 填入的两个参数,第一个是model 注意 这个model是自己创建的 不是属性的model 第二个参数 index。告诉上一个页面需要替换数组中哪个位置的元素 [self.delegate changeValueToListVC:model index:self.index]; } else{ // 直接把自己创建的model 返回去 [self.delegate passValueDelegate:model]; } } [self.navigationController popToRootViewControllerAnimated:YES]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } //照片的设置------------------------------------------------------------ //图片按钮的点击事件 -(void)imagePickerButtonClicked:(UIButton *)sender { UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:@"选取照片" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"相机",@"相册", nil]; [action showFromRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) inView:self.view animated:YES]; } -(void)setImagePickerController:(UIImagePickerControllerSourceType)source { UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; imagePicker.sourceType = source; imagePicker.delegate = self; [imagePicker setEditing:YES]; imagePicker.allowsEditing = YES; //模态推出视图 [self presentViewController:imagePicker animated:YES completion:nil]; } -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { switch (buttonIndex) { case 0: [self setImagePickerController:UIImagePickerControllerSourceTypeCamera]; break; case 1: [self setImagePickerController:UIImagePickerControllerSourceTypePhotoLibrary]; break; default: break; } } -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { //如果图片编辑之后 需要使用 UIImagePickerControllerEditedImage //如果图片没有编辑 只需获取 UIImagePickerControllerOriginalImage // UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"]; //UIImagePNGRepresentation 把图片转化成PNG格式 不压缩比较大 // UIImageJPEGRepresentation 把图片转化成JPEG的格式,第二个参数填的是一个压缩的系数,一般是 0.5 // NSDate *data = UIImagePNGRepresentation(<#UIImage *image#>); //照片传递到上一界面时,这里要进行数据的转化*** self.imageDate = UIImageJPEGRepresentation(image, 0.5); [self.imageButton setImage:image forState:UIControlStateNormal]; [picker dismissViewControllerAnimated:YES completion:nil]; }

 

 

 

LTView.h文件

#import <UIKit/UIKit.h>

@interface LTView : UIView

@property(nonatomic,strong)UILabel *nameLable;

@property(nonatomic,strong)UITextField *messageTextField;

@end

 

 

 LTView.m文件

 


#import "LTView.h"

@implementation LTView

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.nameLable = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 30)];
        //设置字体的大小
        self.nameLable.font = [UIFont systemFontOfSize:15];
        [self addSubview:self.nameLable];
        //字体居中
        self.nameLable.textAlignment = NSTextAlignmentCenter;
        //设置边框宽度
        self.nameLable.layer.borderWidth = 0.5;
        
        self.messageTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 0, self.frame.size.width - 50, 30)];
        //设置边框宽度
        self.messageTextField.layer.borderWidth = 0.5;
        [self addSubview:self.messageTextField];
        
    }

    return self;
}

 

AddressBookModel.h文件

 


#import <Foundation/Foundation.h>

@interface AddressBookModel : NSObject

@property(nonatomic,copy)NSString *name;
@property(nonatomic,copy)NSString *age;
@property(nonatomic,copy)NSString *sex;
@property(nonatomic,copy)NSString *phone;
@property(nonatomic,copy)NSString *content;
@property(nonatomic,copy)NSData *image;


-(id)initWithName:(NSString *)nameStr
              age:(NSString *)age
              sex:(NSString *)sex
            pnone:(NSString *)phone
          content:(NSString *)content
            image:(NSData *)image;







@end

 

AddressBookModel.h文件

 


#import "AddressBookModel.h"

@implementation AddressBookModel



-(id)initWithName:(NSString *)nameStr age:(NSString *)age sex:(NSString *)sex pnone:(NSString *)phone content:(NSString *)content image:(NSData *)image
{

    self = [super init];
    if (self) {
        _name = nameStr;
        _age  = age;
        _sex = sex;
        _phone = phone;
        _content = content;
        _image = image;
                 
    }

    return self;

}



@end

 

 

以下为整体框架的搭建:

 

 

 

效果图:(有点简陋,但基本功能都已实现,添加,删除,修改,添加图片等)

 

 

 

 

 

通讯录整体思路框架结构图:

 

 

posted @ 2015-09-24 20:00  DengHuiCheng  阅读(168)  评论(0编辑  收藏  举报