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];

    }

  • 相关阅读:
    (双指针 二分) leetcode 167. Two Sum II
    (双指针) leetcode 485. Max Consecutive Ones
    (双指针) leetcode 27. Remove Element
    (String) leetcode 67. Add Binary
    (数组) leetcode 66. Plus One
    (N叉树 BFS) leetcode429. N-ary Tree Level Order Traversal
    (N叉树 递归) leetcode 590. N-ary Tree Postorder Traversal
    (N叉树 递归) leetcode589. N-ary Tree Preorder Traversal
    (N叉树 DFS 递归 BFS) leetcode 559. Maximum Depth of N-ary Tree
    (BST 递归) leetcode98. Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/wangxiaorui/p/5023976.html
Copyright © 2011-2022 走看看