zoukankan      html  css  js  c++  java
  • 把自己定义的实体用NSUserDefault保存起来

    NSUserDefaults可以存取一些短小的信息。

    比如存入再读出一个字符串到NSUserDefaults:

    [cpp] view plaincopy
     
    1. NSString *string = [NSString stringWithString @"hahaha"];  
    2. NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];  
    3. [ud setObject:string forKey:@"myKey"];  
    4. NSString *value;  
    5. value = [ud objectForKey:"myKey"];  

    但是并不是所有的东西都能往里放的。NSUserDefaults只支持: NSString, NSNumber, NSDate, NSArray, NSDictionary.

    如果把一个自定义的类存到一个NSArray里,然后再存到NSUserDefaults里也是不能成功的。不信可以试试,如果你成功的请告诉我。

    那怎么办呢?

    我找到的方法是,让这个自定义类实现<NSCoding>协议中的- (id) initWithCoder: (NSCoder *)coder方法和- (void) encodeWithCoder: (NSCoder *)coder方法(obj-c的协议protocol就是java的接口interface,就是C++的纯虚函数),然后把该自定义的类对象编码到NSData中,再从NSUserDefaults中进行读取。

    粘代码:

    假设有这样一个简单的类对象

    [cpp] view plaincopy
     
    1. @interface BusinessCard : NSObject <NSCoding>{  
    2.     NSString *_firstName;  
    3.     NSString *_lastName;  
    4. }  
    5. @property (nonatomic, retain) NSString *_firstName;  
    6. @property (nonatomic, retain) NSString *_lastName;  
    7. @end;  
    8.   
    9. @implementation BusinessCard  
    10. @synthesize _firstName, _lastName;  
    11. - (void)dealloc{  
    12.     [_firstName release];  
    13.     [_lastName release];  
    14.     [super dealloc];  
    15. }  
    16. - (id) initWithCoder: (NSCoder *)coder  
    17. {  
    18.     if (self = [super init])  
    19.     {  
    20.         self._firstName = [coder decodeObjectForKey:@"_firstName"];  
    21.         self._lastName = [coder decodeObjectForKey:@"_lastName"];  
    22.     }  
    23.     return self;  
    24. }  
    25. - (void) encodeWithCoder: (NSCoder *)coder  
    26. {  
    27.     [coder encodeObject:_firstName forKey:@"_firstName"];  
    28.     [coder encodeObject:_lastName forKey:@"_lastName"];  
    29.       
    30. }  
    31.   
    32. @end  

    然后再存取时通过NSData做载体:

    [cpp] view plaincopy
     
    1. BusinessCard *bc = [[BusinessCard alloc] init];  
    2. NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];  
    3. NSData *udObject = [NSKeyedArchiver archivedDataWithRootObject:bc];  
    4. [ud setObject:udObject forKey:@"myBusinessCard"];  
    5. [bc release];  
    6. udObject = nil;  
    7. udObject = [ud objectForKey:@"myBusinessCard"];  
    8. bc = [NSKeyedUnarchiver unarchiveObjectWithData:udObject] ;  
    9.   
    10.       
    11.       

    以上的代码时由另一个程序中截取的,没有测试过,但意思就是这样了。

    如果一个自定义类中由另一个自定义类对象,那么所有嵌套的类都要实现<NSCoding>。

    2————————————————————————————————————————————————————————————》》》》

    创建一个user defaults方法有多个,最简单得快速创建方法:

       NSUserDefaults *accountDefaults = [NSUserDefaults standardUserDefaults];

    添加数据到 user defaults:

       [accountDefaults setObject:nameField.text forKey:UserDefaultNameKey];

    也可以添加基本数据类型int, float, bool等,有相应得方法

       [accountDefaults setBool:YES forKey:UserDefaultBoolKey];

    从user defaults中获取数据:

       [accountDefaults objectForKey:NCUserDefaultNameKey]  

       [accountDefaults boolForKey: UserDefaultBoolKey];

    今天用到NSUserDefault的时候,一直以为[[NSUserDefaults standardUserDefaults] setObject:array forKey:@"testInfo"] ;就算存储好了,再[[NSUserDefaults standardUserDefaults] arrayForKey:@"testInfo"]就算取出来,可是发现重启动程序,关键字testInfo对应的竟然是空,仔细查下资料,发现自己太大意了,忘了写到disk里面了![[NSUserDefaults standardUserDefaults] synchronize]; 涨学问了又。。。呵呵!!!!

    下面贴出代码:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    [defaults setObject:@"111" forKey:@"myTest"];

    [defaults synchronize];

    NSString *testStr = [defaults objectForKey:@"myTest"];

    NSLog(@"testStr is: %@",testStr);

    注意问题:

    通过查看官方文档。UserDefaults不是立即写入,而是根据时间戳定时的把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题。可以通过调用synchornize方法强制写入。

    要点:

    1)NSUserDefaults非常好用,并不需要用户在程序中设置NSUserDefaults的全局变量,需要在哪里使用NSUserDefaults的数据,那么就在哪里创建一个NSUserDefaults对象,然后进行读或者写操作。

    2)针对同一个关键字对应的对象或者数据,可以对它进行重写,重写之后关键字就对应新的对象或者数据,旧的对象或者数据会被自动清理。

    - (void)defaultCheck:(id)sender

    {   

     NSLog(@" check按钮被按下   ");

     NSUserDefaults *accountDefaults = [NSUserDefaults standardUserDefaults];

    if ([accountDefaults boolForKey:NCUserDefaultBoolForRegister] == NO)

     {

      ((UIButton*)sender).selected = YES;

      [accountDefaults setBool:YES forKey:NCUserDefaultBoolForRegister];

      [accountDefaults setObject:nameField.text forKey:NCUserDefaultNameKey];

      [accountDefaults setObject:pwdField.text forKey:NCUserDefaultPasswordKey];

     }

     else {//YES

      ((UIButton*)sender).selected = NO;

      [accountDefaults setBool:NO forKey:NCUserDefaultBoolForRegister];

      [accountDefaults setObject:nil forKey:NCUserDefaultNameKey];

      [accountDefaults setObject:nil forKey:NCUserDefaultPasswordKey];

     }

    }

    - (void)loadView {

     [super loadView];

     nameField = [[UITextField alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];

     pwdField = [[UITextField alloc]initWithFrame:CGRectMake(0, 0, 100, 30)];

     [nameField setCenter:CGPointMake(160, 100)];

     [pwdField setCenter:CGPointMake(160, 150)];

     NSUserDefaults *accountDefaults = [NSUserDefaults standardUserDefaults];

     //存的是bool值一定要用boolForKey:获取

     //如果之前已经保存了User Defaults,那么在读取的时候就要将数据读取出来,显示在用户名和密码框中(这里没有加密)。

     if ([accountDefaults boolForKey:NCUserDefaultBoolForRegister] == YES) {

      nameField.text = [accountDefaults objectForKey:NCUserDefaultNameKey];

      pwdField.text = [accountDefaults objectForKey:NCUserDefaultPasswordKey];

     }

    else

     {

        [nameField setPlaceholder:@"用户名"];

        [pwdField setPlaceholder:@"密码"];

     }

     nameField.borderStyle = UITextBorderStyleBezel;

     [pwdField setBorderStyle:UITextBorderStyleRoundedRect];

     [self.view addSubview:nameField];

     [self.view addSubview:pwdField];

     UIButton * loginBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

     [loginBtn setFrame:CGRectMake(0, 0, 50, 30)];

     [loginBtn setCenter:CGPointMake(200, 200)];

     [loginBtn addTarget:self action:@selector(loginToWeiBo:) forControlEvents:UIControlEventTouchUpInside];

     [self.view addSubview:loginBtn];

     UIButton * checkBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

     [checkBtn setFrame:CGRectMake(0, 0, 20, 20)];

     [checkBtn setCenter:CGPointMake(160, 180)];

      //选中之后得图标

     [checkBtn setBackgroundImage:[UIImage imageNamed:@"lock.png"] forState:(UIControlState)UIControlStateHighlighted];

     [checkBtn setBackgroundImage:[UIImage imageNamed:@"lock.png"] forState:(UIControlState)UIControlStateSelected];

      //未选中

     [checkBtn setBackgroundImage:[UIImage imageNamed:@"unlock.png"] forState:(UIControlState)UIControlStateNormal];

     [checkBtn addTarget:self action:@selector(defaultCheck:) forControlEvents:UIControlEventTouchUpInside];

      //用户名和密码已经保存

     if([accountDefaults boolForKey:NCUserDefaultBoolForRegister] == YES) 

     {

      [checkBtn setSelected:YES];

     }

     [self.view addSubview:Btn];

    }

  • 相关阅读:
    Codeforces 946 A.Partition
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) H.Tree Recovery-完全版线段树(区间更新、区间求和)
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) F.The Biggest Water Problem
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) B.Big Water Problem-完全版线段树(单点更新、区间求和)
    牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) A.逆序数
    POJ 3368.Frequent values-处理数据+RMQ(ST)
    hdu 3033 I love sneakers! 分组背包
    bzoj 2957: 楼房重建 线段树
    hdu 5925 Coconuts 离散化+dfs
    HDU 5929 Basic Data Structure 模拟
  • 原文地址:https://www.cnblogs.com/wangxiaorui/p/5023976.html
Copyright © 2011-2022 走看看