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
以下为整体框架的搭建:
效果图:(有点简陋,但基本功能都已实现,添加,删除,修改,添加图片等)
通讯录整体思路框架结构图: