IOS项目-通讯录_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > IOS项目-通讯录

IOS项目-通讯录

 2015/5/9 10:12:24  chen2013  程序员俱乐部  我要评论(0)
  • 摘要:主要是针对极客学院的通讯录项目,知识点的整理...点击->下载代码1,实现登陆和密码输入框为空时,为不可用状态实现方案:使用添加观察者的方式来实现,在viewDidLoad事件当中添加观察者,来监听nameField和pwdField文本框内容发生改变的事件,内容改变后触发当前类的textChange事件-(void)viewDidLoad{[superviewDidLoad];//添加观察者[[NSNotificationCenterdefaultCenter]addObserver
  • 标签:iOS 项目

主要是针对极客学院的通讯录项目,知识点的整理...点击-> 下载代码

1,实现登陆和密码输入框为空时,为不可用状态

实现方案:使用添加观察者的方式来实现,在viewDidLoad事件当中添加观察者,来监听nameField和pwdField文本框内容发生改变的事件,内容改变后触发当前类的textChange事件

- (void)viewDidLoad {
    [super viewDidLoad];//添加观察者
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.pwdField];
}

--->textChange方法 

- (void)textChange{
    //修改按钮的点击状态
    self.loginBtn.enabled = (self.nameField.text.length && self.pwdField.text.length);
}

 

2,实现页面之间的转跳

自storyboard出来后苹果公司一直很推荐使用storyboard来实现项目,所以prepareForSegue这个方法一直存在于每一个视图控制器当中。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 

这个方法的意思就是跳转之前的准备工作,参数是UIStoryboardSegue,UIStoryboardSegue内有三个属性,1:是identifier(标识),2:sourceViewController(原控制器),3:destinationViewController(目标控制器)

//登陆
- (IBAction)loginAction {
    //点击后执行跳转,LoginToContact为storyboard中segue的标识
    [self performSegueWithIdentifier:@"LoginToContact" sender:nil];
}

跳转之前调用prepareForSegue方法

/*
 一般在这里给下一个控制器传值
 这个sender是当初performSegueWithIdentifier方法传入的sender
*/
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {//1.取得目标控制器
    UIViewController *contactVc = segue.destinationViewController;
    //2.设置标题(传值)
    contactVc.title = [NSString stringWithFormat:@"%@的联系人列表",self.nameField.text];
}

 

3,使用第三方控件MBProgressHUD实现进度提示

在使用之前引入头文件#import "MBProgressHUD+MJ.h",MBProgressHUD+MJ.h是对MBProgressHUD的再一次封装,为了方便使用这个+MJ的。

//登陆
- (IBAction)loginAction {
    if (![self.nameField.text isEqualToString:@"jike"]) {
        [MBProgressHUD showError:@"账号不存在"];
        return;
    }
    if (![self.pwdField.text isEqualToString:@"qq"]) {
        [MBProgressHUD showError:@"密码错误"];
        return;
    }
    //显示蒙版(遮盖)
    [MBProgressHUD showMessage:@"努力加载中"];
    //模拟2秒跳转,以后要发送网络请求
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //移除遮盖
        [MBProgressHUD hideHUD];
        [self performSegueWithIdentifier:@"LoginToContact" sender:nil];
    });
}

 

4,使用UIAlertController

自IOS8.0后UIActionSheet和UIAlertView被UIAlertController取代

- (IBAction)backAction:(id)sender {
    //初始化
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"是否注销?" message:@"真的要注销吗" preferredStyle:UIAlertControllerStyleActionSheet];
    //添加按钮
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
        [self.navigationController popViewControllerAnimated:YES];
    }]];
    //弹出
    [self presentViewController:alert animated:YES completion:NULL];
}

 

5,实现添加页传值

要实现的要点有:a,弹出添加页时弹出小键盘,光标定位到输入框里。来获得更好的用户体验

- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    //让姓名文本框成为第一响应者(叫出键盘)
    [self.nameField becomeFirstResponder];
}

 

b,建立Model文件夹作为模型层,在该文件夹下添加需要传值的模型

#import <Foundation/Foundation.h>

@interface JKContactModel : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *phone;
@end

 

c,定义接口AddViewControllerDelegate,接口内有个方法需要传入AddViewController和JKContactModel
@class 防止相互导入
@property为assign类型,为了防止循环引用

#import <UIKit/UIKit.h>
@class AddViewController,JKContactModel;
@protocol AddViewControllerDelegate <NSObject>

@optional
- (void)addContact:(AddViewController *)addVc didAddContact:(JKContactModel *)contact;
@end

@interface AddViewController : UIViewController
@property (nonatomic, assign) id<AddViewControllerDelegate> delegate;
@end

 

d,在AddViewController下面编写AddAction添加按钮点击事件

respondsToSelector判断某个对象是否实现了某方法

//添加数据
- (IBAction)AddAction {
    //1.关闭当前视图控制器
    [self.navigationController popViewControllerAnimated:YES];
    //代理传值
    //如果它的代理对象响应了我们这个协议方法就进行传值
    if ([self.delegate respondsToSelector:@selector(addContact:didAddContact:)]) {
        JKContactModel *contactModel = [[JKContactModel alloc] init];
        contactModel.name = self.nameField.text;
        contactModel.phone = self.phoneField.text;
        [self.delegate addContact:self didAddContact:contactModel];
    }
}

 

e,最后回到联系人列表控制器ContactTableViewController来响应传值

#pragma mark - AddViewController delagate
- (void)addContact:(AddViewController *)addVc didAddContact:(JKContactModel *)contact{
    //1.添加数据模型
    [self.contactArr addObject:contact];
    //2.刷新表视图
    [self.tableView reloadData];
}

 

f,还有一点要在prepareForSegue方法下设置代理为自己本身

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    AddViewController *addVc = segue.destinationViewController;
    addVc.delegate = self;
}

 

6,实现修改页传值
这个页基本上本上面添加页差不多....没什么知识点好整理的...
这样还是有一个问题,这个ContactTableViewController控制器有两个目标控制器,这样子需要segeue的目标控制器来判断转跳到哪里
修改prepareForSegue方法

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    id vc = segue.destinationViewController;
    if ([vc isKindOfClass:[AddViewController class]]) {//如果是跳转到添加联系人控制器
        //设置代理
        AddViewController *addVc = vc;
        addVc.delegate = self;
    }else if ([vc isKindOfClass:[EditViewController class]]){
        EditViewController *editVc = vc;
        //取得选中的那一行
        NSIndexPath *path = [self.tableView indexPathForSelectedRow];
        editVc.contactModel = self.contactArr[path.row];
        editVc.delagate = self;
    }
}

 

7,UITableView实现滑动删除
UITableView有一个方法叫commitEditingStyle,通过这个方法实现删除功能

#pragma mark - UITableView delagate
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //1.删除数据模型
        [self.contactArr removeObjectAtIndex:indexPath.row];
        //2.刷新表视图
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
    }
}

 

8,偏好设置
要实现的要点有:a,在viewDidLoad事件中加载上次配置

- (void)viewDidLoad {
    [super viewDidLoad];
    //读取上次配置
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    self.nameField.text = [defaults valueForKey:UserNameKey];
    self.pwdField.text = [defaults valueForKey:PwdKey];
    self.rembSwitch.on = [defaults boolForKey:RmbPwdKey];
    if (self.rembSwitch.isOn) {
        self.pwdField.text = [defaults valueForKey:PwdKey];
        self.loginBtn.enabled = YES;
    }   
}


b,在用户登陆成功后保存配置

//登陆
- (IBAction)loginAction {
   //存储数据
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:self.nameField.text forKey:UserNameKey];
    [defaults setObject:self.pwdField.text forKey:PwdKey];
    [defaults setBool:self.rembSwitch.isOn forKey:RmbPwdKey];
    //设置同步
    [defaults synchronize];
}

 

9,对象归档
要实现的要点有:a, NSKeyedArchiver 必须实现NSCoding协议方法

#import "JKContactModel.h"

@implementation JKContactModel
/*
    将某个对象写入文件时候会调用
    在这个方法中说清楚哪些属性需要存储
 */
- (void)encodeWithCoder:(NSCoder *)encoder{
    [encoder encodeObject:self.name forKey:@"name"];
    [encoder encodeObject:self.phone forKey:@"phone"];
}
/*
    解析对象会调用这个方法
    需要解析哪些属性
 */
- (id)initWithCoder:(NSCoder *)decoder{
    if (self = [super init]) {
        self.name = [decoder decodeObjectForKey:@"name"];
        self.phone = [decoder decodeObjectForKey:@"phone"];
    }
    return self;
}
@end


b,然后创建一个归档的文件名,使用到的时候将归档的文件加载至内存当中

#define ContactFilePath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.data"]

@property (nonatomic, strong) NSMutableArray *contactArr;

@implementation ContactTableViewController
- (NSMutableArray *)contactArr{
    if (!_contactArr) {
        //先重归档的文件中读取,如果不存在,则创建一个array
        _contactArr = [NSKeyedUnarchiver unarchiveObjectWithFile:ContactFilePath];
        if (_contactArr == nil) {
            _contactArr  = [NSMutableArray array];
        }
        
    }
    return _contactArr;
}

 

c,需要在数据添加、更新、删除后都应该对数据进行归档

[NSKeyedArchiver archiveRootObject:self.contactArr toFile:ContactFilePath];

 

发表评论
用户名: 匿名