iOS编程------singleton_AddressBook 单例模式 通讯录

本文介绍了一个iOS平台上的通讯录应用程序实现细节,包括AppDelegate、ContactListViewController等关键组件的代码结构与功能实现,展示了如何使用UITableView展示联系人列表,并提供添加、编辑等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//
//  AppDelegate.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;


@end







//
//  AppDelegate.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "AppDelegate.h"
#import "ContactListViewController.h" // 导入联系人列表头文件
@interface AppDelegate ()

@end

@implementation AppDelegate
- (void)dealloc
{
    [_window release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    //
    ContactListViewController *contactVC = [[ContactListViewController alloc] initWithStyle:(UITableViewStylePlain)];
    UINavigationController *naVC = [[UINavigationController alloc] initWithRootViewController:contactVC];
    self.window.rootViewController = naVC;

    [contactVC release];
    [naVC release];

    return YES;

}

@end




////////////////////////////////////////////////////////////////////




//
//  ContactListViewController.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ContactListViewController : UITableViewController

@end





//
//  ContactListViewController.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "ContactListViewController.h"
#import "AddContactViewController.h"
#import "ContactDetailViewController.h"
#import "DataHandle.h"
#import "Contact.h"
#import "ContactCell.h"
@interface ContactListViewController ()
// 单例数据容器
@property (nonatomic, retain)DataHandle *datahandle;
// 联系人列表中的数据容器 -> 指向 单例数据容, 两者保持一致
// 联系人字典
@property (nonatomic, retain) NSMutableDictionary *contactDic;
// key数组
@property (nonatomic, retain) NSMutableArray *keysArray;
@end

@implementation ContactListViewController
- (void)dealloc
{
    [_datahandle release];
    [_contactDic release];
    [_keysArray release];
    [super dealloc];
}


- (void)viewWillAppear:(BOOL)animated {
    _datahandle = [DataHandle shareDataHandle];
    //[self setData];
    [super viewWillAppear:animated];
    [self.tableView reloadData];

}
- (void)setData {
    // 给实例变量赋值
    _datahandle = [DataHandle shareDataHandle];

    // 1.文件路径
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Class25ContactList" ofType:@"plist"];
    // 2.根据根节点, 取出数据
    NSDictionary *sourceDic = [NSDictionary dictionaryWithContentsOfFile:filePath];



    // 3.解析数据, 放入单例容器中

    for (NSString *key in sourceDic) {
        // 取出key对应的数组
        NSArray *oneGroup = sourceDic[key];
        // 创建model数组
        NSMutableArray *modelArray = [NSMutableArray array];

        // 遍历联系人租
        for (NSDictionary *dic in oneGroup) {
            // 创建model对象, kvc赋值, 添加到model数组中
            Contact *contact = [[Contact alloc] init];
            [contact setValuesForKeysWithDictionary:dic];
            [modelArray addObject:contact];
            [contact release];
        }

        // 把解析后的模型数组添加到单例字典中
        [_datahandle.contactDic setObject:modelArray forKey:key];

    }


    // 给单例有序的key值数组赋值
    _datahandle.keysArray = [[[_datahandle.contactDic allKeys] sortedArrayUsingSelector:@selector(compare:)] mutableCopy];

    // 给contactListViewController 的数据容器赋值
    // 本类中数据容器和单例数据容器同步
    self.contactDic = _datahandle.contactDic;
    self.keysArray = _datahandle.keysArray;

}
- (void)viewDidLoad {
    [self setData];
    [super viewDidLoad];
    // 设置标题 通讯录
    self.title = @"通讯录";
    // 数据解析, 把plist文件里面的数据解析为Contact(model) 并且存储到单例数据容器中




    // 设置导航栏按钮
    // 添加
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:(UIBarButtonSystemItemAdd) target:self action:@selector(addNewContact:)];
//    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"添加" style:(UIBarButtonItemStylePlain) target:self action:@selector(addNewContact:)];
//    

    // 编辑
    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    self.navigationItem.rightBarButtonItem.title = @"编辑";

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

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

#pragma mark- 自定义方法
// 获取分区数

- (NSUInteger)numberOfSection {
   // NSLog(@"%lu %s %d", (unsigned long)[_datahandle.keysArray count], __func__, __LINE__);
    return [_datahandle.keysArray count];
    //return [_keysArray count];
}
// 获取分区中行数
- (NSUInteger)numberOfRowsInSection:(NSInteger)section {
   // NSLog(@"%lu %s %d", (unsigned long)[_datahandle.contactDic[_datahandle.keysArray[section]] count], __func__, __LINE__);
    return [_datahandle.contactDic[_datahandle.keysArray[section]] count];
    //return [_contactDic[_keysArray[section]] count];
}

// 获取indexPath对应的联系人
- (Contact *)contactOfIndexPath:(NSIndexPath *)indexPath {
    return _datahandle.contactDic[_datahandle.keysArray[indexPath.section]][indexPath.row];
    //return _contactDic[_keysArray[indexPath.section]][indexPath.row];
}


#pragma mark- Table view data source
#pragma mark- 分区数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
    // Return the number of sections.
    return [self numberOfSection];
}

#pragma mark- 各个分区行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete method implementation.
    // Return the number of rows in the section.
    return [self numberOfRowsInSection:section];
}


#pragma mark- 加载单元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *reuseIdentifier = @"cell";
    /*UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier ];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:reuseIdentifier];
    }
    // Configure the cell...
    Contact *contact = [self contactOfIndexPath:indexPath];
    cell.imageView.image = contact.iconImage;
    cell.textLabel.text = contact.name;
    cell.detailTextLabel.text = contact.phoneNumber;*/
    ContactCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if (cell == nil) {
        cell = [[ContactCell alloc] initWithStyle:(UITableViewCellStyleSubtitle) reuseIdentifier:reuseIdentifier];
    }
    Contact *contact = [self contactOfIndexPath:indexPath];
    [cell setContact:contact];

    return cell;
}

// 设置右边栏
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    return _datahandle.keysArray;
}

// 设置区头标题

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

// 设置每行高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 120;
}

#pragma mark- 当选中单元格执行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //NSLog(@"%ld %ld", indexPath.section, indexPath.row);
    // 选中单元格, 进入联系人详情页面
    // 创建
    ContactDetailViewController *detailVC = [[ContactDetailViewController alloc] init];
    // 设置属性
    detailVC.contact = [self contactOfIndexPath:indexPath];
    detailVC.indexPath = indexPath;
    // push
    [self.navigationController pushViewController:detailVC animated:YES];
    // 释放
    [detailVC release];
}

#pragma mark- 添加联系人
- (void)addNewContact:(UIBarButtonItem *)barButton {
    // 模态显示添加联系人
    AddContactViewController *addContactVC = [[AddContactViewController alloc] init];
   //[self.navigationController presentViewController:addContactVC animated:YES completion:nil];
    // 创建导航控制器
    UINavigationController *naVC =[[UINavigationController alloc] initWithRootViewController:addContactVC];
    // 设置属性

    // 模态
    [self presentViewController:naVC animated:YES completion:nil];
    // 释放
    [addContactVC release];
    [naVC release];
}

#pragma mark- 编辑触发的方法
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [(UITableView *)self.view setEditing:editing animated:animated];
    // 添加判断
    if (editing == YES) {
        self.navigationItem.rightBarButtonItem.title = @"完成";
    } else {
    self.navigationItem.rightBarButtonItem.title = @"编辑";
    }
}

#pragma mark- 指定被编辑行
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}



#pragma mark- 提交编辑
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        if ([_datahandle.contactDic[_datahandle.keysArray[indexPath.section]] count] == 1) {
            [_datahandle.contactDic removeObjectForKey:_datahandle.keysArray[indexPath.section]];

            [_datahandle.keysArray removeObjectAtIndex:indexPath.section];
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:(UITableViewRowAnimationLeft)];
        } else {
            [_datahandle.contactDic[_datahandle.keysArray[indexPath.section]] removeObjectAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

        }
        // Delete the row from the data source
           } else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}



#pragma mark- 完成移动
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
    NSDictionary *contact = _datahandle.contactDic[_datahandle.keysArray[fromIndexPath.section]][fromIndexPath.row];
    [_datahandle.contactDic[_datahandle.keysArray[fromIndexPath.section]] removeObjectAtIndex:fromIndexPath.row];
    [_datahandle.contactDic[_datahandle.keysArray[toIndexPath.section]] insertObject:contact atIndex:toIndexPath.row];
}

#pragma mark- 限制跨区移动
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
    if (sourceIndexPath.section == proposedDestinationIndexPath.section) {
        return proposedDestinationIndexPath;
    } else {
        return sourceIndexPath;
    }
}

#pragma mark- 指定是否可移动
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}


/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end








/////////////////////////////////////////////////////////////////////



//
//  ContactDetailViewController.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>
@class Contact;
@interface ContactDetailViewController : UIViewController
@property (nonatomic, retain) NSIndexPath *indexPath;
// model 属性, 接收前一个页面传递过来的model对象
// 接收被选中单元格的contact

@property (nonatomic, retain) Contact *contact;
@end






//
//  ContactDetailViewController.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "ContactDetailViewController.h"
#import "Contact.h" //导入model
#import "ContactDetailView.h" //导入联系人详情视图
#import "DataHandle.h"
@interface ContactDetailViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
@property (nonatomic, retain)DataHandle *datahandle;
@property (nonatomic, retain)ContactDetailView *detailView;
@property (nonatomic, retain)UIButton *changeButton;
@property (nonatomic, retain)UIImage *image;
@end

@implementation ContactDetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationController.navigationBar.translucent = NO; // 设置为不透明
    // Do any additional setup after loading the view.
    self.title = _contact.name;

    // 创建detailView
    _detailView = [[ContactDetailView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    // 设置model
    _detailView.contact = _contact;
    [_detailView setContactDetailViewEditing:NO];
    _changeButton = [UIButton buttonWithType:(UIButtonTypeSystem)];
    _changeButton.frame = CGRectMake(150, 340, 75, 30);
    [_changeButton setTitle:@"提交" forState:(UIControlStateNormal)];
    [_changeButton addTarget:self action:@selector(changeAction:) forControlEvents:(UIControlEventTouchUpInside)];
    [_detailView addSubview:_changeButton];
    _changeButton.hidden = YES;

    // 添加
    [self.view addSubview:_detailView];

    [_detailView release];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"更改" style:(UIBarButtonItemStylePlain) target:self action:@selector(changeContactInfo:)];


}

- (void)changeContactInfo:(UIBarButtonItem *)rihgtButton{
    [_detailView setContactDetailViewEditing:YES];
    [_detailView.nameLT becomeFirstResponder];
    _changeButton.hidden = NO;
    _detailView.iconImageView.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pickImage:)];
    [_detailView.iconImageView addGestureRecognizer:tap];
    [tap release];




}

- (void)changeAction:(UIButton *)button {
    _datahandle = [DataHandle shareDataHandle];
    NSMutableString *name = [_detailView.nameLT.text mutableCopy];
    CFStringTransform((CFMutableStringRef)name, NULL, kCFStringTransformToLatin, false);
    CFStringTransform((__bridge CFMutableStringRef)name, 0, kCFStringTransformStripDiacritics, NO);
    NSString *groupName = [[name substringToIndex:1] uppercaseString];
    BOOL groupIsExisted = NO;

    _contact.name = _detailView.nameLT.text;
    _contact.age = _detailView.ageLT.text;
    _contact.gender = _detailView.genderLT.text;
    _contact.phoneNumber = _detailView.phoneNumberLT.text;
    _contact.hobby = _detailView.hobbyTV.text;
    _contact.icon = [NSString stringWithFormat:@"%@.jpg", _contact.name];
    if (_image != nil) {
        _contact.iconImage = _image;
    } else {
        _contact.iconImage = _contact.iconImage;
    }

//     [_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] replaceObjectAtIndex:_indexPath.row withObject:_contact];

    //NSLog(@"%@ %@", groupName, _datahandle.keysArray[_indexPath.section]);
    for (NSString *str in _datahandle.keysArray) {
        if ([name isEqualToString:str]) {
            groupIsExisted = YES;
        }
    }

    if ([_datahandle.keysArray[_indexPath.section] isEqualToString:groupName]) {
         [_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] replaceObjectAtIndex:_indexPath.row withObject:_contact];
    } else {

//        if ([_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] count] == 1) {
//            [_datahandle.contactDic removeObjectForKey:_datahandle.keysArray[_indexPath.section]];
//            [_datahandle.keysArray removeObjectAtIndex:_indexPath.section];
//            NSLog(@"%@",_datahandle.contactDic[groupName] );
//            [_datahandle.contactDic[groupName] addObject:_contact];
//            NSLog(@"%@",_datahandle.contactDic[groupName] );
//            
//            
//        } else {
//            [_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] removeObjectAtIndex:_indexPath.row];
//            [_datahandle.contactDic[groupName] addObject:_contact];
//        }
        if (groupIsExisted == YES) {
            if ([_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] count] == 1) {
                [_datahandle.contactDic removeObjectForKey:_datahandle.keysArray[_indexPath.section]];
                [_datahandle.keysArray removeObjectAtIndex:_indexPath.section];
                NSLog(@"%@",_datahandle.contactDic[groupName] );
                [_datahandle.contactDic[groupName] addObject:_contact];
                NSLog(@"%@",_datahandle.contactDic[groupName] );


            } else {
                [_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] removeObjectAtIndex:_indexPath.row];
                [_datahandle.contactDic[groupName] addObject:_contact];
            }

        } else {
            NSMutableArray *arr = [NSMutableArray array];

            if ([_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] count] == 1) {
                [_datahandle.contactDic removeObjectForKey:_datahandle.keysArray[_indexPath.section]];
                [_datahandle.keysArray removeObjectAtIndex:_indexPath.section];

            } else {
                [_datahandle.contactDic[_datahandle.keysArray[_indexPath.section]] removeObjectAtIndex:_indexPath.row];

            }
            [arr addObject:_contact];
            [_datahandle.contactDic setObject:arr forKey:groupName];
            _datahandle.keysArray = [[[_datahandle.contactDic allKeys] sortedArrayUsingSelector:@selector(compare:)] mutableCopy];
        }
    }

    [_detailView setContactDetailViewEditing:NO];
    _changeButton.hidden = YES;
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    // 1.取出图片, 原始图片
    UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
    // 2.把图片赋值给imageView
    _detailView.iconImageView.image = image;
    _image = [image retain];
    // 3.模态消失
    [picker dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark- 处理tap事件
- (void)pickImage:(UITapGestureRecognizer *)tap {
    // 1.创建一个UIImagePickerController
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];

    // 2.设置选择照片类型
    [picker setSourceType:(UIImagePickerControllerSourceTypePhotoLibrary)];

    // 3.设置代理
    picker.delegate = self;

    // 4.模态现实
    [self presentViewController:picker animated:YES completion:nil];

}



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

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end







/////////////////////////////////////////////////////////////////////




//
//  AddContactViewController.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>

@interface AddContactViewController : UIViewController

@end






//
//  AddContactViewController.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "AddContactViewController.h"
#import "ContactDetailView.h"
#import "DataHandle.h"
#import "Contact.h"

@interface AddContactViewController ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property (nonatomic, retain) ContactDetailView *addView;

@property (nonatomic, retain)DataHandle *datahandle;
// 联系人列表中的数据容器 -> 指向 单例数据容, 两者保持一致
//// 联系人字典
//@property (nonatomic, retain) NSMutableDictionary *contactDic;
//// key数组
//@property (nonatomic, retain) NSMutableArray *keysArray;
@property (nonatomic, retain)UIImage *image;
@end

@implementation AddContactViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"添加联系人";
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationController.navigationBar.translucent = NO;
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:(UIBarButtonItemStylePlain) target:self action:@selector(gotoContactList:)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"确认" style:(UIBarButtonItemStylePlain) target:self action:@selector(addContact:)];


    // Do any additional setup after loading the view.
    _addView = [[ContactDetailView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [_addView setContactDetailViewEditing:YES];

     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pickImage:)];
    [_addView.iconImageView addGestureRecognizer:tap];
    [tap release];
    _addView.iconImageView.userInteractionEnabled = YES;
    [self.view addSubview:_addView];
    [_addView release];

    _datahandle = [DataHandle shareDataHandle];

}

#pragma mark- 返回联系人列表
- (void)gotoContactList:(UIBarButtonItem *)leftButton {
    [self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark- 添加联系人
- (void)addContact:(UIBarButtonItem *)rightButton {

    if ([_addView.nameLT.text length] == 0 || [_addView.phoneNumberLT.text length] == 0) {
        UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"提示" message:@"添加不成功" delegate:self cancelButtonTitle:@"确认" otherButtonTitles:@"取消", nil];
        [message show];
    } else {
        // 根据中文获得拼音
        NSMutableString *name = [_addView.nameLT.text mutableCopy];
        CFStringTransform((CFMutableStringRef)name, NULL, kCFStringTransformToLatin, false);
        CFStringTransform((__bridge CFMutableStringRef)name, 0, kCFStringTransformStripDiacritics, NO);
        // 生成字典
        NSDictionary *contactDic = @{@"name" : _addView.nameLT.text, @"gender" : _addView.genderLT.text, @"phoneNumber" : _addView.phoneNumberLT.text, @"hobby" : _addView.hobbyTV.text, @"picture" : @""};
        // 获取分组名
        NSString *groupName = [[name substringToIndex:1] uppercaseString];
        Contact *contact = [[Contact alloc] init];

        // kvc转化为对象
        [contact setValuesForKeysWithDictionary:contactDic];
        contact.iconImage = _image;
        NSMutableArray *group = [_datahandle.contactDic objectForKey:groupName];
        if (group) {
            [group addObject:contact];
        } else {
            group = [NSMutableArray array];
            [group addObject:contact];
            [_datahandle.contactDic setValue:group forKey:groupName];
            _datahandle.keysArray = [[[_datahandle.contactDic allKeys] sortedArrayUsingSelector:@selector(compare:)] mutableCopy];
        }

        UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"提示" message:@"添加成功" delegate:self cancelButtonTitle:@"确认" otherButtonTitles:@"取消", nil];
        [message show];
    }
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    // 1.取出图片, 原始图片
    UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
    // 2.把图片赋值给imageView
    _addView.iconImageView.image = image;
    _image = [image retain];
    // 3.模态消失
    [picker dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark- 处理tap事件
- (void)pickImage:(UITapGestureRecognizer *)tap {
    NSLog(@"2222");
    // 1.创建一个UIImagePickerController
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];

    // 2.设置选择照片类型
    [picker setSourceType:(UIImagePickerControllerSourceTypePhotoLibrary)];

    // 3.设置代理
    picker.delegate = self;

    // 4.模态现实
    [self presentViewController:picker animated:YES completion:nil];

}


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



/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end







/////////////////////////////////////////////////////////////////////




//
//  DataHandle.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <Foundation/Foundation.h>

@interface DataHandle : NSObject

// 联系人字典
@property (nonatomic, retain) NSMutableDictionary *contactDic;
// 有序字典键key数组
@property (nonatomic, retain) NSMutableArray *keysArray;

// 单例类 创建单例对象的方法, 类方法
+ (DataHandle *)shareDataHandle;
@end






//
//  DataHandle.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "DataHandle.h"

@implementation DataHandle

- (void)dealloc
{
    [_contactDic release];
    [_keysArray release];
    [super dealloc];
}

// 单例对象 特征
// 1.从任何页面都能放问到
// 2.不会释放, 生命周期从创建出来与程序同步
// 3.每次通过单例类方法创建的都是同一个对象


// 1.设置为全局变量, 放在静态区, 静态修饰符
static DataHandle *handle = nil;

// 2.创建单例的方法
+ (DataHandle *)shareDataHandle {

    // 线程安全考虑, 添加同步锁
    @synchronized(self) { // 当有多个线程访问的时候, 等待一个线程访问完了, 另外一个线程才执行

    // 判断handle是否已经创建, 没有则开辟空间
    if (handle == nil) {
        handle = [[DataHandle alloc] init];
    }

    // 创建过了, 则直接返回已经创建的对象
    return handle;
    }
}


// 重写init方法给容器成员变量开辟空间
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.contactDic = [NSMutableDictionary dictionary];
        self.keysArray = [NSMutableArray array];
    }
    return self;
}
@end







////////////////////////////////////////////////////////////////////




//
//  Contact.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface Contact : NSObject

@property (nonatomic, copy) NSString *name; // 姓名
@property (nonatomic, copy) NSString *gender; // 性别
@property (nonatomic, copy) NSString *age; // 年龄
@property (nonatomic, copy) NSString *phoneNumber; // 手机
@property (nonatomic, copy) NSString *hobby; // 爱好
@property (nonatomic, copy) NSString *icon; // 图片
@property (nonatomic, retain) UIImage *iconImage; // 个人图片
@end





//
//  Contact.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "Contact.h"

@implementation Contact
- (void)dealloc
{
    [_name release];
    [_gender release];
    [_age release];
    [_phoneNumber release];
    [_hobby release];
    [_icon release];
    [_iconImage release];
    [super dealloc];
}

// kvc 赋值时候需要注意
// 1.一般我们尽量保持Model属性名和字典key值相同, 特殊情况除外, 如: id
// 2.如果dictionary key值和属性名不同, 需要特殊处理

// kvc一般赋值, 属性名和key值相同时调用给方法
- (void)setValue:(id)value forKey:(NSString *)key {
    [super setValue:value forKey:key];
    // 处理特殊逻辑
    // 给icon字符串赋值的时候, 同时给iconImage赋值
}
// kvc特殊赋值, 当属性名和key值不相同时调用
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    // 如果是picture对应的赋值, 把value赋值给icon, 同时给iconImage赋值
    if ([key isEqual:@"picture"]) {
        self.icon = value;
        self.iconImage = [UIImage imageNamed:value];
    }
}


@end








//////////////////////////////////////////////////////////////////





//
//  ContactDetailView.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>
@class Contact;
@interface ContactDetailView : UIView
@property (nonatomic, retain, readonly) UIImageView *iconImageView;//图片
@property (nonatomic, retain, readonly) UITextField *nameLT; //姓名
@property (nonatomic, retain, readonly) UITextField *genderLT; // 性别
@property (nonatomic, retain, readonly) UITextField *ageLT;// 年龄
@property (nonatomic, retain, readonly) UITextField *phoneNumberLT; // 手机号
@property (nonatomic, retain, readonly) UITextView *hobbyTV; // 爱好

// model
@property (nonatomic, retain) Contact *contact;


// 是否可编辑
- (void)setContactDetailViewEditing:(BOOL)edit;

@end







//
//  ContactDetailView.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "ContactDetailView.h"
#import "Contact.h"
@implementation ContactDetailView
- (void)dealloc
{
    [_iconImageView release];
    [_nameLT release];
    [_genderLT release];
    [_ageLT release];
    [_phoneNumberLT release];
    [_hobbyTV release];
    [_contact release];
    [super dealloc];
}

// 重写initWithFrame方法
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //_iconImageView
        _iconImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 20, 120, 180)];
        _iconImageView.backgroundColor = [UIColor grayColor];
        [self addSubview:_iconImageView];

        // nameLT
        _nameLT = [[UITextField alloc] initWithFrame:CGRectMake(140, 20, 200, 30)];
        [self addSubview:_nameLT];

        // genderLT
        _genderLT = [[UITextField alloc] initWithFrame:CGRectMake(140, 60, 95, 30)];
        [self addSubview:_genderLT];

        // ageLT
        _ageLT = [[UITextField alloc] initWithFrame:CGRectMake(245, 60, 95, 30)];
        [self addSubview:_ageLT];

        // phoneNumberLT
        _phoneNumberLT = [[UITextField alloc] initWithFrame:CGRectMake(140, 100, 200, 30)];
        [self addSubview:_phoneNumberLT];

        // hobbyTV
        _hobbyTV = [[UITextView alloc] initWithFrame:CGRectMake(10, 210, 335, 100)];
        _hobbyTV.backgroundColor = [UIColor cyanColor];
        [self addSubview:_hobbyTV];
    }
    return self;
}

// 设置可编辑状态
- (void)setContactDetailViewEditing:(BOOL)edit {
    // 如果是可编辑的则打开用户交互
    if(edit == YES) {
        // 编辑状态
        [self contactDetailViewStateEditing];
    } else {
        // 显示状态
        [self contactDetailViewStateShowing];
    }
}

// 可显示状态
- (void)contactDetailViewStateShowing {
    // 关闭用户交互
    _iconImageView.userInteractionEnabled = NO;
    _nameLT.enabled = NO;
    _genderLT.enabled = NO;
    _ageLT.enabled = NO;
    _phoneNumberLT.enabled = NO;
    _hobbyTV.editable = NO;

    // 设置borderStyle
    _nameLT.borderStyle = UITextBorderStyleLine;
    _genderLT.borderStyle = UITextBorderStyleLine;
    _ageLT.borderStyle = UITextBorderStyleLine;
    _phoneNumberLT.borderStyle = UITextBorderStyleLine;

}

/// 可编辑状态
- (void)contactDetailViewStateEditing {
    // 关闭用户交互
    _iconImageView.userInteractionEnabled = YES;
    _nameLT.enabled = YES;
    _genderLT.enabled = YES;
    _ageLT.enabled = YES;
    _phoneNumberLT.enabled = YES;
    _hobbyTV.editable = YES;

    // 设置borderStyle
    _nameLT.borderStyle = UITextBorderStyleRoundedRect;
    _genderLT.borderStyle = UITextBorderStyleRoundedRect;
    _ageLT.borderStyle = UITextBorderStyleRoundedRect;
    _phoneNumberLT.borderStyle = UITextBorderStyleRoundedRect;

    // 设置占位符
    _nameLT.placeholder = @"姓名";
    _genderLT.placeholder = @"性别";
    _ageLT.placeholder = @"年龄";
    _phoneNumberLT.placeholder = @"联系方式";
}


- (void)setContact:(Contact *)contact {
    if (_contact != contact) {
        [_contact release];
        _contact = [contact retain];
    }

    // 给内部空间赋值
    _iconImageView.image = _contact.iconImage;
    _nameLT.text = _contact.name;
    _ageLT.text = _contact.age;
    _genderLT.text = _contact.gender;
    _phoneNumberLT.text = _contact.phoneNumber;
    _hobbyTV.text = _contact.hobby;
}



/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end






/////////////////////////////////////////////////////////////////////






//
//  ContactCell.h
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import <UIKit/UIKit.h>
@class Contact;
@interface ContactCell : UITableViewCell
@property (nonatomic, retain, readonly) UIImageView *iconImage;
@property (nonatomic, retain, readonly) UILabel *nameLable;
@property (nonatomic, retain, readonly) UILabel *phoneNumber;

@property (nonatomic, retain) Contact *contact;
@end






//
//  ContactCell.m
//  UI12_singleton_AddressBook
//
//  Created by l on 15/9/16.
//  Copyright (c) 2015年 . All rights reserved.
//

#import "ContactCell.h"
#import "Contact.h"
@implementation ContactCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _iconImage = [[UIImageView alloc] initWithFrame:CGRectMake(3, 5, 90, 110)];
        [self.contentView addSubview:_iconImage];
        _nameLable = [[UILabel alloc] initWithFrame:CGRectMake(105, 5, 120, 30)];
        [self.contentView addSubview:_nameLable];
        _phoneNumber = [[UILabel alloc] initWithFrame:CGRectMake(105, 50, 160, 30)];
        [self.contentView addSubview:_phoneNumber];

    }
    return self;
}

- (void)setContact:(Contact *)contact {
    if (_contact != contact) {
        [_contact release];
        _contact = [contact retain];
    }
    _iconImage.image = contact.iconImage;
    _nameLable.text = contact.name;
    _phoneNumber.text = contact.phoneNumber;
}



- (void)awakeFromNib {
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值