分析{功能分析(打电话、添加联系人、修改联系人),模块分析(联系人展示、详情模块、添加模块)}
拿到一个项目,首先分析项目框架(工程框架)
首先:判断是否是用户第一次安装:(如果是的,那就加载用户引导页面)(如果不是,那就显示用户联系人的主页面)
其次:用户联系人的主页面VC(用一个协助类 addressbookheleper类(做数据处理相关的内容,属于MVC的M层。只处理相关的数据,这里是为VC瘦身)去提供相应的方法 给 controller (ContactListViewController) )这里面有这几个方法:为VC提供tableViewCell某一分区得到行数、分区个数、对应的分区的标题、右侧的索引、是否要删除某分区、是否要删除某一行、移动某分区的某一行、返回对应行的联系人、添加联系人。
#import "AppDelegate.h"
#import "ContactListViewController.h"
#import "MainNavigationController.h"//程序导航栏是同样的风格,所以这里用公用的类
@interface AppDelegate ()
@implementation AppDelegate
-(void)dealloc{
[_window release];
[super dealloc];
}
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
//判断是否是第一次安装
//如果是,则指定为引导用户页为第一启动(为 window 的跟视图控制器)否则进入程序的主页面
//设置 根视图控制器
ContactListViewController * mainVC = [[ContactListViewController alloc]initWithStyle:UITableViewStylePlain];
//创建导航控制器
MainNavigationController * navl = [[MainNavigationController alloc]initWithRootViewController:mainVC];
//指定为 window 根视图控制器
self.window.rootViewController = navl;
//释放所有权
[mainVC release];
[navl release];
return YES;
}
Appdelegate.m文件
#import
#import "Contact.h"
@interface AddressBookHelper : NSObject
//提供相应的方法,给对应的 controller (ContactListViewController)
(NSInteger)numberOfSection;//返回分区个数
(NSInteger)numberOfRowsInSection:(NSInteger)section;//返回对应分区的行数
(NSString *)titleForHeaderInSection:(NSInteger)section;//返回对应分区的标题
(NSArray *)sectionIndexTitles;//返回右侧索引的标题
#pragma mark---delete
(BOOL)isNeedToDeleteWholeSection:(NSInteger)section;//是否要删除整个分区
(void)deleteWholeSection:(NSInteger)section;//删除整个分区
(void)deleteRowAtIndexPath:(NSIndexPath *)indexPath;//删除一行
#pragma mark---move
#pragma mark---返回对应行所需的联系人
#pragma mark---添加联系人
+(void)addContact:(Contact *)newContact;
方法的声明
//
// AddressBookHelper.m
#import "AddressBookHelper.h"
#import
/*
AddressHelper 类 是通讯录列表的界面的辅助类,帮助(ContactListViewController )做数据处理相关的内容,为 ContactListViewController 瘦身,该类可有可无 属于 MVC 的 M 层的类
M层的类 只处理相关的数据(和数据有关的类都是M层)如:数据解析类 数据请求类 数据本地化
*/
@interface AddressBookHelper ()
//存储外层的大字典
@property(nonatomic,retain)NSMutableDictionary * dataSource;
//存储拍好序的 key
@property(nonatomic,retain)NSMutableArray * sortedKeys;
@implementation AddressBookHelper
static AddressBookHelper * helper ;//让生命周期与程序的生命周期一致
//单例方法
//获取本地文件
-(void)readDataFromPlist{
//获取文件。获取外层字典的信息
NSString * filePath = [[NSBundle mainBundle] pathForResource:kPlistName ofType:@"plist"];
NSDictionary * dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
self.dataSource = [NSMutableDictionary dictionaryWithCapacity:dict.count];
//2.1遍历外层字典的key
for (NSString * key in dict) {
// NSArray * group = [dict objectForKey:key];
//2.2通过key 获取联系人分组数据
NSArray * group = dict[key];
//2.3创建一个可变数组 来存放联系人对象
NSMutableArray * perArr = [NSMutableArray arrayWithCapacity:group.count];
//2.4遍历分组数组 获得联系人小字典
for (NSDictionary * dic in group) {
//2.5将对象封装到字典
Contact * contact = [[Contact alloc]initWithDic:dic];
//2.6将联系人字典添加到存放对象的数组
[perArr addObject:contact];
[contact release];
}
//2.7将存放对象的数组以及key 存放到 大字典里
[self.dataSource setObject:perArr forKey:key];//(可变字典可以这样格式写,不可变的不能这样写)
//获得排好序的 key
NSArray * sorted = [[_dataSource allKeys]sortedArrayUsingSelector:@selector(compare:)];
self.sortedKeys = [NSMutableArray arrayWithArray:sorted];
}
}
//提供相应的方法,给对应的 controller (ContactListViewController)
//返回分区个数
//返回对应分区的行数
//返回对应分区的标题
//返回右侧索引的标题
#pragma mark---delete
//是否要删除整个分区
//删除整个分区
(void)deleteWholeSection:(NSInteger)section{
//1.获取对应的 key
NSString * key = helper.sortedKeys[section];
//2.从字典中删除 key 的分组数组
[helper.dataSource removeObjectForKey:key];
//3.从key 数组中删除 key
[helper.sortedKeys removeObject:key];
/*
//从字典删除对应的分组的数组
[helper.dataSource removeObjectForKey:helper.sortedKeys[section]];
//从拍好序的 key 数组中移除 key 值
[helper.sortedKeys removeObjectAtIndex:section];
*/
}
//删除一行
#pragma mark---move
//移动某分区某行
(void)moveFromIndexPath:(NSIndexPath *)sourceIndexPath ToIndexPath:(NSIndexPath *)destinationindexPath{
/*
//获取对应分组的数组
NSMutableArray * group = helper.dataSource[helper.sortedKeys[sourceIndexPath.section]];
//获取对应的联系人
Contact * per =[[group objectAtIndex:sourceIndexPath.row]retain];
//从对应位置移除
[group removeObjectAtIndex:sourceIndexPath.row];
//插入联系人
[group insertObject:per atIndex:destinationindexPath.row];
*/
NSString * key = [helper.sortedKeys objectAtIndex:sourceIndexPath.section];
NSMutableArray * group = [helper.dataSource objectForKey:key];
Contact * per = [[group objectAtIndex:sourceIndexPath.row]retain];
[group removeObjectAtIndex:sourceIndexPath.row];
[group insertObject:per atIndex:destinationindexPath.row];
[per release];
}
#pragma mark---返回对应行所需的联系人
(Contact *)contactAtIndexPath:(NSIndexPath *)indexPath{
//测试的假数据
// Contact * per = [[Contact alloc]initWithDic:@{@"name":@"张三",@"gender":@"男",@"phoneNum":@"13523526303",@"photo":@"jia"}];
// return per;
Contact * per = helper.dataSource[helper.sortedKeys[indexPath.section]][indexPath.row];
return per;
//对的写法
// NSArray * group = helper.dataSource[helper.sortedKeys[indexPath.section]];
// Contact * per = group[indexPath.row];
// return per;
//对
// return helper.dataSource[helper.sortedKeys[indexPath.section]][indexPath.row];
}
#pragma mark---添加联系人
+(void)addContact:(Contact *)newContact{
}
-(void)dealloc{
self.dataSource = nil;
self.sortedKeys = nil;
[super dealloc];
}
方法的实现
并提供相对应的借口,供VC里的数据处理使用
然后:在联系人的主页面要实现对数据与用户页面的交互功能
#import
@interface ContactListViewController : UITableViewController
、、、、、、、ContactListViewController.m文件
//
// ContactListViewController.m
#import "ContactListViewController.h"
#import "AddressBookHelper.h"
#import "Contact.h"
#import "AddContactViewController.h"
#import "MainNavigationController.h"
#import "DetailViewController.h"
#import "CustomContactCellTabviewCell.h"
@interface ContactListViewController ()
@implementation ContactListViewController
(void)viewDidLoad {
[super viewDidLoad];
[self customizedNavBar];//配置该页面的导航条
//注册 cell
[self.tableView registerClass:[CustomContactCellTabviewCell class] forCellReuseIdentifier:@"reuse"];
}
#pragma mark---配置该页面的导航条
-(void)customizedNavBar{
self.navigationItem.title = @"XXXX通讯录";
self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem * left = [[UIBarButtonItem alloc]initWithImage:[[UIImage imageNamed:@"add_contact"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(handleAddAction:)];
self.navigationItem.leftBarButtonItem = left;
[left release];
}
#pragma mark---模态进入添加联系人页面
-(void)handleAddAction:(UIBarButtonItem *)sender{
AddContactViewController * addContactVC = [[AddContactViewController alloc]init];
MainNavigationController * mainVC = [[MainNavigationController alloc]initWithRootViewController:addContactVC];
mainVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:mainVC animated:YES completion:^{
}];
[addContactVC release];
[mainVC release];
}
#pragma mark--内存警告处理
(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] && !self.view.window) {
self.view = nil;
}
}
#pragma mark - UITableViewDataSource 两个必须实现方法
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// 通过助手类 返回分区的个数
return [AddressBookHelper numberOfSection];
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// 通过助手类 返回分区的行数
return [AddressBookHelper numberOfRowsInSection:section];
}
#pragma mark---信息展示
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return [AddressBookHelper titleForHeaderInSection:section];
}
#pragma mark---右侧的索引的标题
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return [AddressBookHelper sectionIndexTitles];
}
#pragma mark--- cell 行高设置
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ;
}
#pragma mark---tableViewcell 是否可以编辑
/* */
#pragma mark---重写方法去编辑 tableviewcell
#pragma mark---移动操作
#pragma mark---移动设置(cell是否可以移动)
#pragma makr---限制移动的范围,禁止跨区移动
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
if (sourceIndexPath.section == proposedDestinationIndexPath.section) {
return proposedDestinationIndexPath;
}
return sourceIndexPath;
}
#pragma mark---点击进入详情页面 (UITableViewDelegate)
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//push 进入联系人详情页面
DetailViewController * detailVC = [[DetailViewController alloc]init];
//属性传值
\[self.navigationController pushViewController:detailVC animated:YES\];
\[detailVC release\];
}
#pragma mark---MakeACallDelegate 协议方法实现
//拨打电话
-(void)dial:(NSIndexPath *)indexPath{
Contact * contact = [AddressBookHelper contactAtIndexPath:indexPath];
UIWebView * webview = [[UIWebView alloc]init];
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"tel:%@",contact.phoneNum]]]];
[webview release];
}
ContactListViewController.m & .h文件
其中要用到的数据层类 M
Contact.h文件
#import
@interface Contact : NSObject
@property(nonatomic,copy)NSString * name;
@property(nonatomic,copy)NSString * gender;
@property(nonatomic,copy)NSString * phoneNum;
@property(nonatomic,copy)NSString * photo;
-(instancetype)initWithDic:(NSDictionary *)dic;
@end
Contact.m 文件
#import "Contact.h"
@implementation Contact
-(instancetype)initWithDic:(NSDictionary *)dic{
self = [super init];
if (self) {
//KVC 赋值
[self setValuesForKeysWithDictionary:dic];
}
return self;
}
//对应的KVC 赋值的错误安全处理
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
-(void)dealloc{
self.name = nil;
self.gender = nil;
self.phoneNum = nil;
self.photo = nil;
[super dealloc];
}
@end
contact.h & .m 文件
视图类 V
#import
@class Contact;
//为 callBtn 制订协议,实现拨打电话
@protocol MakeACallDelegate
-(void)dial:(NSIndexPath *)indexPath;
@interface CustomContactCellTabviewCell : UITableViewCell
@property (nonatomic ,retain) UIImageView *photoView;
@property (nonatomic ,retain) UILabel *nameLabel;
@property (nonatomic ,retain) UILabel *phoneLabel;
@property (nonatomic ,retain) UIButton *callBtn;
@property(nonatomic,assign)id
@property(nonatomic,retain)NSIndexPath * indexPath;//存储当前点击 call 的索引
@property(nonatomic,retain)Contact * contact;//声明一个联系人对象的属性
//为cell 上的控件赋值
-(void)configureCell:(Contact *)contact;
@end
//
// CustomContactCellTabviewCell.m
#import "CustomContactCellTabviewCell.h"
#import "Contact.h"
#import "AddressBookHelper.h"
@implementation CustomContactCellTabviewCell
(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self.contentView addSubview:self.photoView];
[self.contentView addSubview:self.nameLabel];
[self.contentView addSubview:self.phoneLabel];
[self.contentView addSubview:self.callBtn];
}
return self;
}
#pragma lazy loading 实现控件的创建
(UIImageView *)photoView {
if (!_photoView) {
self.photoView = [[UIImageView alloc] initWithFrame:CGRectMake(, , , )];
_photoView.layer.cornerRadius = 5.0;
_photoView.layer.masksToBounds = YES;
}
return [[_photoView retain]autorelease];
}
}
}
(UIButton *)callBtn {
if (!_callBtn) {
self.callBtn = [UIButton buttonWithType:UIButtonTypeSystem];
_callBtn.frame = CGRectMake(self.frame.size.width - , , , );
//添加触发
[_callBtn addTarget:self action:@selector(handleCall:) forControlEvents:UIControlEventTouchUpInside];
[_callBtn setImage:[UIImage imageNamed:@"action_call"] forState:UIControlStateNormal];
}
return _callBtn;
}
#pragma mark---打电话按钮
(void)handleCall:(UIButton *)sender {
if (!_delegate && [_delegate respondsToSelector:@selector(dial:)]) {
[_delegate dial:self.indexPath];
}
}
(void)dealloc {
self.nameLabel = nil;
self.photoView = nil;
self.phoneLabel = nil;
self.callBtn = nil;
[super dealloc];
}
(void)awakeFromNib {
// Initialization code
}
(void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
//第一种 : 自定义方法实现对 cell 的控件的赋值
-(void)configureCell:(Contact *)contact{
self.nameLabel.text = contact.name;
self.phoneLabel.text = contact.phoneNum;
self.photoView.image = [UIImage imageNamed:contact.photo];
}
//第二种 :重写 setter 方法 为 cell 上的方法赋值
/*
-(void)setContact:(Contact *)contact{
if (_contact != contact) {
[_contact release];
_contact = [contact retain];
}
self.nameLabel.text = contact.name;
self.phoneLabel.text = contact.phoneNum;
self.photoView.image = [UIImage imageNamed:contact.photo];
}
*/
contactContactCelltableCell.h & .m 文件
其他参考:参考
手机扫一扫
移动阅读更方便
你可能感兴趣的文章