Fork me on https://github.com

UITableView综合通讯录实战 (调用系统相册 UIImagePickerController)

UITableView综合

通讯录实战

Controller

HomeTableViewController.m
#import "HomeTableViewController.h"
#import "DetailViewController.h"
#import "AddViewController.h"
#import "DataHandle.h"
#import "Person.h"

@interface HomeTableViewController () {
    DataHandle *datahandle;
}
@end

@implementation HomeTableViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"通 讯 录";
    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:(UIBarButtonSystemItemAdd) target:self action:@selector(add)] autorelease];
    self.tableView.rowHeight = 110;
    self.tableView.tableFooterView = [[UIView new] autorelease];
    
    datahandle = [DataHandle defaultDataHandle];
}

- (void)add {
//    AddViewController *addVC = [[AddViewController alloc] init];
//    [self.navigationController pushViewController:addVC animated:YES];
//    [addVC release];

    UINavigationController管理的视图控制器, 都是具有明显层级关系的, 页面的切换使用push和pop
    当页面之间没有明显的层级关系, 页面跳转使用模态形式做切换
    
    模态切换的步骤
    1.创建下一个页面
    AddViewController *addVC = [[AddViewController alloc] init];
    模态切换的两个视图是没有层级关系的, 并且后一个视图不会继承前一个视图的导航栏, 后一个视图的导航栏需要自己来加
    UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:addVC];
    修改动画效果
    navigation.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    2.从当前页面, 模态切换到下一个页面
    [self presentViewController:navigation animated:YES completion:^{
        NSLog(@"已经切换");
    }];
    3.释放
    [addVC release];
    [navigation release];
}

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

#pragma mark - UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return datahandle.titleArray.count;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return datahandle.titleArray[section];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return datahandle.titleArray;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    /*
    //获取分区标题
    NSString *key = datahandle.titleArray[section];
    //通过标题, 获取对应value(存放联系人数组)
    NSMutableArray *array = datahandle.personDic[key];
     */
    //返回
    return [[datahandle.personDic valueForKey:datahandle.titleArray[section]] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier ];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:identifier];
    }
    数组某个person对象
    Person *person = [datahandle.personDic valueForKey:datahandle.titleArray[indexPath.section]][indexPath.row];
    在cell上显示
    cell.textLabel.text = person.name;
    cell.detailTextLabel.text = person.phone;
    cell.imageView.image = person.image;
    NSLog(@"%@", datahandle.titleArray);
    
    return cell;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //删除数据
        BOOL result = [datahandle deletePersonWithIndexPath:indexPath];
        if (result) {
            //创建分区位置
            NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:indexPath.section];
            //删除分区
            [tableView deleteSections:indexSet withRowAnimation:(UITableViewRowAnimationFade)];
        } else {
            //删除cell
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:(UITableViewRowAnimationFade)];
        }
    }
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    [datahandle movePersonAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    当时视图将要出现的时候, 刷新数据
    [self.tableView reloadData];
}

#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    往单例内存数据
//    DataHandle *dataHandle = [DataHandle defaultDataHandle];
//    dataHandle.name = [NSString stringWithFormat:@"%ld分区%ld行", indexPath.section, indexPath.row];
//
    DetailViewController *detailVC = [[DetailViewController alloc] init];
    datahandle.person = datahandle.personDic[datahandle.titleArray[indexPath.section]][indexPath.row];
    [self.navigationController pushViewController:detailVC animated:YES];
}

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
    判断是否同一个区
    if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
        return sourceIndexPath;
    } else {
        return proposedDestinationIndexPath;
    }
}
@end

 

DetailViewController.m
#import "DetailViewController.h"
#import "DataHandle.h"
#import "Person.h"

@interface DetailViewController ()
@end
@implementation DetailViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor colorWithRed:0.986 green:1.000 blue:0.569 alpha:1.000];
    
    从单例中取数据
//    DataHandle *dataHandle = [DataHandle defaultDataHandle];
//    self.navigationItem.title = dataHandle.name;
   
    DataHandle *handle = [DataHandle defaultDataHandle];
    self.navigationItem.title = handle.person.name;
    
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.jpg"]];
    imageView.frame = CGRectMake(20, 100, 113, 160);
    imageView.userInteractionEnabled = YES;
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    imageView.image =handle.person.image;
    [self.view addSubview:imageView];
    [imageView release];
    
    NSArray *array = @[handle.person.name, handle.person.gender, handle.person.age, handle.person.phone];
    for (NSInteger i = 0; i < 4; i++) {
        UILabel *label = [[UILabel alloc] init];
        label.text = array[i];
        label.tag = 101 + i;
        label.backgroundColor = [UIColor whiteColor];
        [self.view addSubview:label];
        [label release];
    }
    
    UILabel *nameLabel = (UILabel *)[self.view viewWithTag:101];
    nameLabel.frame = CGRectMake(143, 100, 375 - 163, 40);
    
    UILabel *genderLabel = (UILabel *)[self.view viewWithTag:102];
    genderLabel.frame = CGRectMake(143, 160, (375 - 173) / 2, 40);
    
    UILabel *ageLabel = (UILabel *)[self.view viewWithTag:103];
    ageLabel.frame = CGRectMake( CGRectGetMaxX(genderLabel.frame) + 10, 160, (375 - 173) / 2 , 40);
    
    UILabel *phoneLabel = (UILabel *)[self.view viewWithTag:104];
    phoneLabel.frame = CGRectMake(143, 220, 375 - 163, 40);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end
AddViewController.m
#import "AddViewController.h"
#import "Person.h"
#import "DataHandle.h"
#import "HomeTableViewController.h"

@interface AddViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property (nonatomic, retain) UIImageView *imageView;
@property (nonatomic, retain) UITextField *nameTextField, *genderTextField, *ageTextField, *phoneTextField;

@end

@implementation AddViewController

- (void)dealloc {
    [_imageView release];
    [_nameTextField release];
    [_genderTextField release];
    [_ageTextField release];
    [_phoneTextField release];
    [super dealloc];
}

- (void)viewDidLoad {
    [super viewDidLoad];
   
    self.view.backgroundColor = [UIColor colorWithRed:0.805 green:1.000 blue:0.934 alpha:1.000];
    self.navigationItem.title = @"添加联系人";
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:(UIBarButtonSystemItemCancel) target:self action:@selector(cancel)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:(UIBarButtonSystemItemSave) target:self action:@selector(save)];
    
//    self.imageView = [UIImage imageNamed:@"1.jpg"];
//    UIImageView *image = [[UIImageView alloc] initWithImage:_imageView];
    self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"1.jpg"]];
    self.imageView.frame = CGRectMake(20, 100, 113, 160);
    self.imageView.userInteractionEnabled = YES;
    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    [self.view addSubview:self.imageView];
    [self.imageView release];
    
    NSArray *array = @[@"姓名", @"性别", @"年龄", @"电话号码"];
    for (NSInteger i = 0; i < 4; i++) {
        UITextField *textField = [[UITextField alloc] init];
        textField.borderStyle = UITextBorderStyleRoundedRect;
        textField.placeholder = array[i];
        textField.clearsOnInsertion = YES;
        textField.tag = 101 + i;
        [self.view addSubview:textField];
        [textField release];
    }
    
    self.nameTextField = (UITextField *)[self.view viewWithTag:101];
    self.nameTextField.frame = CGRectMake(143, 100, 375 - 163, 40);
    
    self.genderTextField = (UITextField *)[self.view viewWithTag:102];
    self.genderTextField.frame = CGRectMake(143, 160, (375 - 173) / 2, 40);
    
    self.ageTextField = (UITextField *)[self.view viewWithTag:103];
    self.ageTextField.frame = CGRectMake( CGRectGetMaxX(self.genderTextField.frame) + 10, 160, (375 - 173) / 2 , 40);
    
    self.phoneTextField = (UITextField *)[self.view viewWithTag:104];
    self.phoneTextField.frame = CGRectMake(143, 220, 375 - 163, 40);
    //创建手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
    [self.imageView addGestureRecognizer:tap];
    [tap release];
   }

- (void)save {
    if (self.nameTextField.text.length == 0 || self.phoneTextField.text.length == 0) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"姓名或电话不能为空" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [alertView show];
        [alertView release];
        return;
    }
    
    创建一个person对象
    Person *person = [[Person alloc] init];
    person.name = self.nameTextField.text;
    person.gender = self.genderTextField.text;
    person.age = self.ageTextField.text;
    person.phone = self.phoneTextField.text;
    person.image = self.imageView.image;
    
    把person对象存入单例
    DataHandle *dataHandle = [DataHandle defaultDataHandle];
    [dataHandle addPerson:person];
    [person release];
    
    返回
    [self dismissViewControllerAnimated:YES completion:nil];
  }

- (void)tap {
    调用系统相册
    UIImagePickerController, 系统相册, 继承于UINavigationController
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    [self presentViewController:picker animated:YES completion:^{
        NSLog(@"系统相册");
    }];
    
}
- (void)cancel {
    模态返回
    [self dismissViewControllerAnimated:YES completion:^{
        NSLog(@"已经返回");
    }];
}

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

#pragma mark - UIImagePickerControllerDelegate

//已经完成图片选择
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
    self.imageView.image = image;
    [picker dismissViewControllerAnimated:YES completion:nil];
}

Model

 Person.h
#import <Foundation/Foundation.h>
只有导入UIKit的框架, 才能使用UI开头的类
#import <UIKit/UIKit.h>

@interface Person : NSObject

@property (nonatomic, retain) UIImage *image;
@property (nonatomic, retain) NSString *name, *gender, *age, *phone;

@end
Person.m
#import "Person.h"

@implementation Person
- (void)dealloc {
    [_image release];
    [_name release];
    [_gender release];
    [_age release];
    [_phone release];
    [super dealloc];
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"name: %@ gender: %@ age: %@ phone: %@", _name, _gender, _age, _phone];
}
@end
 DataHandle.h
#import <Foundation/Foundation.h>

单例模式, 保证一个类生成的对象只有一个

注意
1.通过单例模式封装的类, 创建对象必须使用defaultDataHandle方法
2.单例模式创建的对象, 不用释放, 当程序结束时会自动释放
3.单例模式创建的对象, 不能存过大的数据
@class Person;
@interface DataHandle : NSObject

//@property (nonatomic, retain) NSString *name;
当项目中很多页面都会使用到某个数据时(比如通讯录中各个页面都会使用联系人信息), 一般都会把这个数据存放到单例中
@property (nonatomic, retain) NSMutableDictionary *personDic;
@property (nonatomic, retain) NSMutableArray *titleArray;
@property (nonatomic, retain) Person *person;

创建单例的方法
1.类方法
2.返回值类型: 当前类
3.方法名: main/default/shared + 类名
+ (DataHandle *)defaultDataHandle;

添加联系人
- (void)addPerson:(Person *)person;

删除联系人
- (BOOL)deletePersonWithIndexPath:(NSIndexPath *)indexpath;

移动联系人
- (void)movePersonAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;

@end
Person.m
#import "DataHandle.h"
#import "Person.h"

@implementation DataHandle

- (void)dealloc {
//    [_name release];
    [_personDic release];
    [_titleArray release];
    [super dealloc];
}

+ (DataHandle *)defaultDataHandle {
    static DataHandle *datahandle = nil;
    if (datahandle == nil) {
        datahandle = [[DataHandle alloc] init];
        数组和字典必须初始化, 开辟内存空间后, 才能使用
        加号方法, self相当于类DataHandle
        调用setter方法, 应该使用对象
        datahandle.personDic = [NSMutableDictionary dictionaryWithCapacity:0];
        datahandle.titleArray = [NSMutableArray arrayWithCapacity:0];
    }
    return datahandle;
}

- (void)addPerson:(Person *)person {
    汉字转拼音
    NSMutableString *mutableString = [NSMutableString stringWithString:person.name];
    CFStringTransform((CFMutableStringRef)mutableString, NULL, kCFStringTransformToLatin, false);
    mutableString = (NSMutableString *)[mutableString stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:[NSLocale currentLocale]];
    获取首字母, 并且转成大写
    NSString *firstLetter = [[mutableString substringToIndex:1] uppercaseString];
   
    if ([firstLetter compare:@"A"] == -1 || [firstLetter compare:@"Z"] == 1) {
        firstLetter = @"#";
    }
    通过首字母从字典中找对应的数组
    NSMutableArray *array = [_personDic objectForKey:firstLetter];
     if (array == nil) {
        数组是不存在的
        创建数组
        array = [NSMutableArray arrayWithCapacity:1];
        把person添加到数组中
        [array addObject:person];
        [_personDic setObject:array forKey:firstLetter];
    } else {
        数组已经存在
        直接把person添加到数组中
        [array addObject:person];
    }
     NSLog(@"%@", [self.personDic allKeys]);
    //    _titleArray = [[_personDic allKeys] mutableCopy];
}

重写getter方法, 为titleArray赋值
- (NSMutableArray *)titleArray {
    排序: 冒泡排序, 提供两个各元素的比较方法, 提供相邻两个元素的比较规则
    NSArray *sortArray = [self.personDic.allKeys sortedArrayUsingSelector:@selector(compare:)];
    self.titleArray = [[sortArray mutableCopy] autorelease];
//    NSLog(@"%@", self.titleArray);
    return _titleArray;
}

- (BOOL)deletePersonWithIndexPath:(NSIndexPath *)indexpath {
    当你重写getter方法以后, 使用变量是, 使用self
    分区标题
    NSString *key = self.titleArray[indexpath.section];
    获取标题对应的数组
    NSMutableArray *array = _personDic[key];
    
    判断数组中是否只有一个元素
    if (array.count == 1) {
        一个元素, 删除键值对
        [self.personDic removeObjectForKey:key];
        return YES;
    } else {
        多个元素, 删除数组中的某个元素
        [array removeObjectAtIndex:indexpath.row];
        return NO;
    }
  }

- (void)movePersonAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    标题对应的数组
    NSMutableArray *array = self.personDic[self.titleArray[sourceIndexPath.section]];
    保留原来的数据
    Person *person = [array[sourceIndexPath.section] retain];
    移除数组中的数据
    [array removeObject:person];
    插入到数组的某个位置
    [array insertObject:person atIndex:destinationIndexPath.row];
    释放
    [person release];
}

@end

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2015-11-03 20:40  OrangesChen  阅读(375)  评论(0编辑  收藏  举报