• 私人通讯录



    这里给出大部分基本的代码


    联系人模型对象:

    #import "NJContatc.h"
    
    @implementation NJContatc
    
    - (void)encodeWithCoder:(NSCoder *)aCoder
    {
        [aCoder encodeObject:self.name forKey:@"name"];
        [aCoder encodeObject:self.phoneNumber forKey:@"number"];
    }
    
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        if (self = [super init]) {
            self.name = [aDecoder decodeObjectForKey:@"name"];
            self.phoneNumber = [aDecoder decodeObjectForKey:@"number"];
        }
        return self;
    }
    @end



    登录控制器中:

    1.在viewDidLoad页面刚载入进来的时候,

    给两个文本输入框加入通知 NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

    并注冊监听文本变化 [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.acountField]

    2.因为记住password和自己主动登录都属于偏好设置,所以这样的数据要保存到偏好设置中。第一次载入要去除信息:

    NSUserDefaults *defaults = [NSUserDefaults standarUserDefaults];

    3.使用完通知后,须要移除监听

    [[NSNotificationCenter defaultCenter] removeObserver:self];

    4.注意两个Switch的逻辑

    取消记住password,肯定也取消了自己主动登录

    选择了自己主动登录,肯定勾选了记住password

    5.在点击登录button之后,须要加入一些特效。此时能够使用别人写的HUD,并设置延迟几秒跳转,简单介绍模仿网络请求延迟

    使用dispatch_after snippet - GCD Dispatch After 方法,设置延迟时间可块内容

    6.点击成功后。通过设置segue的identifier的值:login2contact 。

    使用 [self performSegueWithIdentifier:@"login2contact" sender:@"jonathan"];跳转到联系人界面(这是手动运行segue)

    7.在成功跳转之前。还须要拿到segue的目标控制器

    在固定的prepareForSegue方法中通过[segue.destinationViewController],拿到目标页面的控制器


    
    #import "NJLoginViewController.h"
    #import "MBProgressHUD+NJ.h"
    
    #define NJAccount @"account"
    #define NJPwd @"pwd"
    #define NJRemPwd @"remPwd"
    #define NJAutoLogin @"autoLogin"
    
    
    @interface NJLoginViewController ()<UITextFieldDelegate>
    /**
     *  账号输入框
     */
    @property (weak, nonatomic) IBOutlet UITextField *accountField;
    /**
     *  password输入框
     */
    @property (weak, nonatomic) IBOutlet UITextField *pwdField;
    /**
     *  登录button
     */
    @property (weak, nonatomic) IBOutlet UIButton *loginBtn;
    /**
     *  点击记住password
     */
    - (IBAction)remPwdChange:(id)sender;
    /**
     *  点击自己主动登录
     */
    - (IBAction)autoLoginChange:(id)sender;
    /**
     *  记住password
     */
    @property (weak, nonatomic) IBOutlet UISwitch *remPwdSwitch;
    /**
     *  自己主动登录
     */
    @property (weak, nonatomic) IBOutlet UISwitch *autoLoginSwitch;
    /**
     *  点击登录button
     */
    - (IBAction)loginOnClick:(UIButton *)sender;
    
    @end
    
    @implementation NJLoginViewController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 监听文本输入框的改变
        // 1.拿到通知中心
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        // 2.注冊监听
        // 注意点: 一定要写上通知的公布者
        [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.accountField];
        [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.pwdField];
        
        // 3. 回显数据(读取保存的偏好设置信息)
       NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        // 设置账号
        self.accountField.text = [defaults objectForKey:NJAccount];
        // 设置password
        // 推断是否须要记住password
    //    BOOL isSavePwd = [defaults boolForKey:NJRemPwd];
    //    [self.remPwdSwitch setOn:isSavePwd animated:YES];
        
        [self.remPwdSwitch setOn:[defaults boolForKey:NJRemPwd] animated:YES];
        
        if (self.remPwdSwitch.isOn) {
            self.pwdField.text = [defaults objectForKey:NJPwd];
        }
        
    //    BOOL isAutoLogin = [defaults boolForKey:NJAutoLogin];
        [self.autoLoginSwitch setOn:[defaults boolForKey:NJAutoLogin] animated:YES];
        if (self.autoLoginSwitch.isOn) {
            // 自己主动登录相当于调用登录方法
            [self loginOnClick:nil];
        }
        
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    - (void)textChange
    {
        self.loginBtn.enabled = (self.accountField.text.length > 0  &&
        self.pwdField.text.length > 0);
    }
    
    - (IBAction)remPwdChange:(id)sender
    {
        // 1.推断是否记住password
        if (self.remPwdSwitch.isOn == NO) {
            // 2.假设取消记住password取消自己主动登录
    //        self.autoLoginSwitch.on = NO;
            [self.autoLoginSwitch setOn:NO animated:YES];
        }
    }
    
    - (IBAction)autoLoginChange:(id)sender
    {
        // 1.推断是否自己主动登录
        if (self.autoLoginSwitch.isOn) {
            // 2.假设自己主动登录就记住password
            [self.remPwdSwitch setOn:YES animated:YES];
        }
    }
    
    - (IBAction)loginOnClick:(UIButton *)sender
    {
        // 加入蒙版禁止用户操作, 而且提示用户正在登录
        [MBProgressHUD showMessage:@"正在拼命载入ing...."];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (![self.accountField.text isEqualToString:@"lnj"]) {
                // 3.登录成功后移除蒙版
                [MBProgressHUD hideHUD];
                 [MBProgressHUD showError:@"username不对!!!"];
                return;
            }
            
            if (![self.pwdField.text isEqualToString:@"123"]) {
                // 3.登录成功后移除蒙版
                [MBProgressHUD hideHUD];
                [MBProgressHUD showError:@"password不对!!!"];
                 return;
            }
            
            // 3.登录成功后移除蒙版
            [MBProgressHUD hideHUD];
            // 4.假设正如,跳转到联系人界面(手动运行segue)
            [self performSegueWithIdentifier:@"login2contatc" sender:@"jonathan"];
            
            // 5.保存用户数据
            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
            [defaults setObject:self.accountField.text forKey:NJAccount];
            [defaults setObject:self.pwdField.text forKey:NJPwd];
            [defaults setBool:self.remPwdSwitch.isOn forKey:NJRemPwd];
            [defaults setBool:self.autoLoginSwitch.isOn forKey:NJAutoLogin];
            [defaults synchronize];
            
         });
    }
    
    // 在segue跳转之前调用, 会传入performSegueWithIdentifier方法创建好的segue对象
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        // 1.拿到目标控制器
        UIViewController *vc =  segue.destinationViewController;
        // 2.设置目标控制器的标题
        vc.title = [NSString stringWithFormat:@"%@ 的联系人列表", self.accountField.text];
    
    }
    @end
    


    联系人控制器中:

    1.默认在UIBarButtonItem中仅仅能手动加入一左一右两个button,要向再加入button,须要代码实现

    加入一个有点击事件的编辑button,通过[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editBtnClick)];

    self.navigationItem.rightBarButtonItems = @[editBtn,addBtn];

    2.使用UIActionSheet 设置左上角注销button。点击注销后。通过popViewController方法弹回到登录界面

    3.因为在联系人界面会有两个跳转界面,所以须要推断segue的目标控制器

    因为无论是手动还是自己主动类型的segue。在跳转前都会运行prepareForSegue方法,所以这个推断就能够在这种方法里写

    通过获取到目标控制器对象vc,使用isKindOfClass推断,并各自设置代理

    4.接下来就是运行各自的代理方法

    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomaininMask,YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"];

    [NSKeyedArchiver archiverRootObject:self.contacts toFile:path];

    最后不要忘记刷新[self.tableView reloadData];

    5.控件是通过xib或者storyboard创建出来的就会调用awakeFrmeNib方法,且仅仅调用一次

    在这种方法中把UIView类型的切割线加入到self.contentView中,注意。不要直接将自控件加入到cell 中

    6.当控件的frame被改动时会调用layoutSubviews方法,重写不论什么方法都要先[super layoutSubviews]


    #import "NJContatcsViewController.h"
    #import "NJAddViewController.h"
    #import "NJContatc.h"
    #import "NJEditViewController.h"
    #import "NJContatcCell.h"
    
    #define NJContactsPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"]
    
    
    @interface NJContatcsViewController ()<UIActionSheetDelegate, NJAddViewControllerDelegate, NJEditViewControllerDelegate>
    /**
     *  点击注销button
     */
    - (IBAction)logout:(UIBarButtonItem *)sender;
    
    /**
     *  保存全部用户数据
     */
    @property (nonatomic, strong) NSMutableArray *contatcs;
    @end
    
    @implementation NJContatcsViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        
        // 给当前控制器的当行控制器加入一个button
        UIBarButtonItem *addBtn = self.navigationItem.rightBarButtonItem;
        UIBarButtonItem *editBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editBtnClick)];
        
        self.navigationItem.rightBarButtonItems = @[editBtn, addBtn];
    }
    
    - (void)editBtnClick
    {
    //    NSLog(@"editBtnClick");
        // 开启tableview的编辑模式
    //    self.tableView.editing = !self.tableView.editing;
        [self.tableView setEditing:!self.tableView.editing animated:YES];
    }
    
    - (IBAction)logout:(UIBarButtonItem *)sender
    {
        UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"确定要注销?" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:nil];
        [sheet showInView:self.view];
        
    }
    #pragma mark - UIActionSheetDelegate
    - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        if (0 != buttonIndex) return;
        
        // 移除栈顶控制器
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    // 不管是手动类型的segue还是自己主动类型的segue, 在跳转之前都会运行该方法
    // 控制器跳转之前(运行segue之前)运行
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        // 0.推断目标控制器是加入还是编辑
        // 1.取出目标控制器
        UIViewController *vc = segue.destinationViewController;
        if ([vc isKindOfClass:[NJAddViewController class]]) {
            NJAddViewController *addVc = (NJAddViewController *)vc;
            // 2.设置代理
            addVc.delegate = self;
        }else if ([vc isKindOfClass:[NJEditViewController class]]){
            // 传递数据
            NJEditViewController *editVc = (NJEditViewController *)vc;
            
            // 通过tableview获取被点击的行号
            NSIndexPath *path = [self.tableView indexPathForSelectedRow];
            // 取出被点击行的模型
            NJContatc *c = self.contatcs[path.row];
            NSLog(@"联系人列表 %p" , c);
            // 赋值模型
            editVc.contatc = c;
            // 设置代理
            editVc.delegate = self;
        }
    }
    
    #pragma mark - NJEditViewControllerDelegate
    - (void)editViewControllerDidClickSavBtn:(NJEditViewController *)editViewController contatc:(NJContatc *)cpmtatc
    {
        // 0.更新保存的数据
    //    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"];
        [NSKeyedArchiver archiveRootObject:self.contatcs toFile:NJContactsPath];
        
        // 1.刷新表格
        [self.tableView reloadData];
    }
    
    #pragma mark - NJAddViewControllerDelegate
    - (void)addViewControllerDidAddBtn:(NJAddViewController *)editViewController contatc:(NJContatc *)contatc
    {
        // 1.保存数据到数组中
        [self.contatcs addObject:contatc];
        
        // 在这个地方保存用户加入的全部的联系人信息
    //    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject ] stringByAppendingPathComponent:@"contacts.arc"];
        [NSKeyedArchiver archiveRootObject:self.contatcs toFile:NJContactsPath];
        
        
        // 2.刷新表格
        [self.tableView reloadData];
    }
    
    #pragma mark - 数据源方法
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.contatcs.count;
    }
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 1.创建cell
        NJContatcCell *cell  = [NJContatcCell cellWithTableView:tableView];
        // 2.设置模型
        // 设置数据
        NJContatc *c = self.contatcs[indexPath.row];//0
        cell.contatc = c;
        // 2.返回cell
        return cell;
    }
    
    // 仅仅在在tableview的编辑模式下才有加入
    
    // 仅仅要实现该方法, 手指在cell上面滑动的时候就自己主动实现了删除button
    // commitEditingStyle: 传入提交的编辑操作(删除/加入)
    // forRowAtIndexPath: 当前正在编辑的行
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
    //    NSLog(@"%d", indexPath.row);
        
        if (UITableViewCellEditingStyleDelete == editingStyle) {
            // 1.改动数据
            [self.contatcs removeObjectAtIndex:indexPath.row];
            // 2.刷新表格
            // reloadData会又一次调用数据的全部方法,刷新全部的行
            //    [self.tableView reloadData];
            
            // 该方法用于删除tableview上指定行的cell
            // 注意:使用该方法的时候,模型中删除的数据的条数必须和deleteRowsAtIndexPaths方法中删除的条数一致,否则会报错
            // 简而言之,就删除的数据必须和删除的cell保持一致
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
            
            // 3.更新保存的文件
            [NSKeyedArchiver archiveRootObject:self.contatcs toFile:NJContactsPath];
    
        }else if (UITableViewCellEditingStyleInsert == editingStyle)
        {
            // 加入一条数据
    //        NSLog(@"加入一条数据");
            
            // 1.改动数据
            NJContatc *c = [[NJContatc alloc] init];
            c.name = @"xff";
            c.phoneNumber = @"123456";
    
    //        [self.contatcs addObject:c];
            [self.contatcs insertObject:c atIndex:indexPath.row + 1];
            
    //        NJContatc *c1 = [[NJContatc alloc] init];
    //        c1.name = @"xzz";
    //        c1.phoneNumber = @"123456";
    //        [self.contatcs insertObject:c1 atIndex:indexPath.row + 2];
            
            // 2.刷新表格
    //        [self.tableView reloadData];
            
            NSIndexPath *path = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
            // 注意点:数组中插入的条数必须和tableview界面上插入的cell条一致
            // 否则程序会报错
            [self.tableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationBottom];
        }
    
    }
    
    // 用于告诉系统开启的编辑模式是什么模式
    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    //    NSLog(@"indexPath = %d", indexPath.row);
    //    return UITableViewCellEditingStyleInsert;
        
        if (indexPath.row % 2 == 0) {
            return UITableViewCellEditingStyleInsert;
        }else
        {
            return UITableViewCellEditingStyleDelete;
        }
    }
    
    #pragma mark - 懒载入
    - (NSMutableArray *)contatcs
    {
        if (_contatcs == nil) {
            
            // 1.获取路径
    //        NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"contacts.arc"];
            // 2.从文件里读取数组
            _contatcs =  [NSKeyedUnarchiver unarchiveObjectWithFile:NJContactsPath];
            
            // 3.假设第一次启动没有文件,就创建一个空的数组用于保存数据
            if (_contatcs == nil) {
                _contatcs = [NSMutableArray array];
            }
            
        }
        return _contatcs;
    }
    
    @end
    

    加入控制器:

    #import "NJAddViewController.h"
    //#import "NJContatcsViewController.h"
    #import "NJContatc.h"
    
    @interface NJAddViewController ()
    @property (weak, nonatomic) IBOutlet UITextField *nameField;
    @property (weak, nonatomic) IBOutlet UITextField *phoneField;
    @property (weak, nonatomic) IBOutlet UIButton *addBtn;
    /**
     *  点击加入button
     */
    - (IBAction)addBtnOnClick:(UIButton *)sender;
    
    @end
    
    @implementation NJAddViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 监听文本输入框的改变
        
        // 1.拿到通知中心
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        // 2.注冊监听
        // 注意点: 一定要写上通知的公布者
        [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField];
        [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.phoneField];
    
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        // 3.主动召唤出键盘
        [self.nameField becomeFirstResponder];
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    - (void)textChange
    {
        self.addBtn.enabled = (self.nameField.text.length > 0  &&
                                 self.phoneField.text.length > 0);
    }
    
    - (IBAction)addBtnOnClick:(UIButton *)sender
    {
        // 0. 移除栈顶控制器
        [self.navigationController popViewControllerAnimated:YES];
        
        // 1.获取用户输入的姓名和电话
        NSString *name = self.nameField.text;
        NSString *phone = self.phoneField.text;
        
        NJContatc *c = [[NJContatc alloc] init];
        c.name = name;
        c.phoneNumber = phone;
    
        // 2.传递数据给联系人列表
        if ([self.delegate respondsToSelector:@selector(addViewControllerDidAddBtn: contatc:)]) {
            [self.delegate addViewControllerDidAddBtn:self contatc:c];
        }
        
    }
    @end
    

    编辑控制器:

    #import "NJAddViewController.h"
    //#import "NJContatcsViewController.h"
    #import "NJContatc.h"
    
    @interface NJAddViewController ()
    @property (weak, nonatomic) IBOutlet UITextField *nameField;
    @property (weak, nonatomic) IBOutlet UITextField *phoneField;
    @property (weak, nonatomic) IBOutlet UIButton *addBtn;
    /**
     *  点击加入button
     */
    - (IBAction)addBtnOnClick:(UIButton *)sender;
    
    @end
    
    @implementation NJAddViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 监听文本输入框的改变
        
        // 1.拿到通知中心
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        // 2.注冊监听
        // 注意点: 一定要写上通知的公布者
        [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.nameField];
        [center addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:self.phoneField];
    
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        // 3.主动召唤出键盘
        [self.nameField becomeFirstResponder];
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    - (void)textChange
    {
        self.addBtn.enabled = (self.nameField.text.length > 0  &&
                                 self.phoneField.text.length > 0);
    }
    
    - (IBAction)addBtnOnClick:(UIButton *)sender
    {
        // 0. 移除栈顶控制器
        [self.navigationController popViewControllerAnimated:YES];
        
        // 1.获取用户输入的姓名和电话
        NSString *name = self.nameField.text;
        NSString *phone = self.phoneField.text;
        
        NJContatc *c = [[NJContatc alloc] init];
        c.name = name;
        c.phoneNumber = phone;
    
        // 2.传递数据给联系人列表
        if ([self.delegate respondsToSelector:@selector(addViewControllerDidAddBtn: contatc:)]) {
            [self.delegate addViewControllerDidAddBtn:self contatc:c];
        }
        
    }
    @end
    


  • 相关阅读:
    centos在设置时区
    Qt那点事儿(三) 论父对象与子对象的关系
    Qt多线程应用--QRunnable
    Qt学习之如何启动和终止一个线程
    Qt 互斥量 QMutex
    Qt网络获取本机网络信息
    QT程序拷贝 转移 改变运行环境
    Qt调用dll中的功能函数
    用Qt生成dll类库及调用方法
    Qt DLL总结【二】-创建及调用QT的 DLL
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6780884.html
Copyright © 2020-2023  润新知