高级UIKit-04(NSUserDefaults、NSKeyedArchiver、对象归档方法)
【day05_1_UserDefault】:判断应用程序是否是第一次运行
NSUserDefaults:用来保存应用程序的配置信息如:程序运行次数,用户登陆信息等。
// 使用系统提供的NSUserDefaults对象判断 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; int runCount = [[userDefaults objectForKey:@"runCount"] intValue]; if (runCount == 0) { NSLog(@"第一次运行!!!"); } runCount++; [userDefaults setObject:[NSNumber numberWithInt:runCount] forKey:@"runCount"]; [userDefaults synchronize]; // 同步
练习:三个界面ABC,运行次数奇数次进C,偶数次进B
在MXAppDelegate.m中写
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 因为那个箭头可以直接确定谁是rootViewController,所以可以简化代码 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; int runCount = [[userDefaults objectForKey:@"runCount"] intValue]; if (runCount % 2 == 0) { UIViewController *bVC = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"bVC"]; [self.window.rootViewController presentViewController:bVC animated:YES completion:nil]; self.window.rootViewController = bVC; } runCount++; [userDefaults setObject:[NSNumber numberWithInt:runCount] forKey:@"runCount"]; [userDefaults synchronize]; // 同步 return YES; }
【day05_2_ArrayArchiver】:数组归档的使用
归档的使用:把对象转成二进制NSData,可以进行保存或网络传输
如何实现归档:需要让对象实现NSCoding协议
已经实现了NSCoding协议的对象有:数组和字典
数组归档:
// 数组归档 NSArray *namesArray = @[@"张三",@"李四",@"王五"]; // 1.创建可变的data对象,装数据 NSMutableData *data = [NSMutableData data]; // 2.创建归档对象 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; // 3.把对象编码 [archiver encodeObject:namesArray forKey:@"names"]; // 4.编码完成 [archiver finishEncoding]; // 5.保存归档 [data writeToFile:@"/Users/tarena/Desktop/namesArchiver" atomically:YES];
数组反归档:
// 数组反归档 // 1.得到data NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena/Desktop/namesArchiver"]; // 2.创建反归档对象 NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; // 3.解码并存到数组中 NSArray *namesArray = [unArchiver decodeObjectForKey:@"names"]; // 4.循环打印 for (NSString *name in namesArray) { NSLog(@"%@",name); }
【day05_3_DictionaryArchiver】字典的归档反归档和数组一样。
【day05_4_AddStringToArchiver】:添加输入框内容到textView中,关闭程序后textView中内容还在,(让UITextView不可编辑,勾掉Editable)
这个使用到归档,代码:
// 加载数组归档数据 -(void)loadInfo{ // 从归档中取数据 // 数组反归档 self.namesTextView.text = @""; NSData *nameData = [NSData dataWithContentsOfFile:@"/Users/tarena/Desktop/nameArrayArchiver"]; // 得到data NSKeyedUnarchiver *unarc = [[NSKeyedUnarchiver alloc] initForReadingWithData:nameData]; // 创建反归档对象 self.nameArray = [unarc decodeObjectForKey:@"names"]; // 解码 for (NSString *name in self.nameArray) { // 取出数组中数据拼接到textView self.namesTextView.text = [self.namesTextView.text stringByAppendingFormat:@"%@\n",name]; } } // 添加姓名 - (IBAction)addNameToTextView:(id)sender { NSString *name = self.nameTextField.text; // 取出输入的字符串 NSMutableArray *mutableNameArray = [NSMutableArray arrayWithArray:self.nameArray]; // 把不可变数组变为可变数组 [mutableNameArray addObject:name]; // 添加字符串到数组中 // 数组归档 NSMutableData *nameData = [NSMutableData data]; // 创建可变data对象 NSKeyedArchiver *arc = [[NSKeyedArchiver alloc] initForWritingWithMutableData:nameData]; // 创建归档对象 [arc encodeObject:mutableNameArray forKey:@"names"]; // 给数组编码 [arc finishEncoding]; // 编码完成 [nameData writeToFile:@"/Users/tarena/Desktop/nameArrayArchiver" atomically:YES]; // 保存到指定的路径 [self loadInfo]; }
总结:反归档如果返回数组,一般用NSArray接收,如果在程序中要改变NSArray的值,要先把它转成可变数组,然后把这个新数组重新归档。
注意归档时,要创建可变的NSData对象。
【day05_5_ArchiverPerson】:对象可以归档反归档必须做的事
1.遵守NSCoding协议
2.实现该协议的两个方法
代码如下:
// 属性编码 - (void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeInteger:self.age forKey:@"age"]; } // 属性解码 - (id)initWithCoder:(NSCoder *)aDecoder{ self = [super init]; if (self) { self.name = [aDecoder decodeObjectForKey:@"name"]; self.age = [aDecoder decodeIntegerForKey:@"age"]; } return self; }
【day05_6_PersonsArchiver】:人员名单,功能有添加人员,删除人员,修改人员。使用归档。
添加:
添加时要跳转到新的界面,一般这么做:
1.如果第一个界面用navigation包含了就把整个界面push到第二个界面,使用viewController连接。
2.然后设置该连线也就是segue的identifier值。
3.然后第一个界面中的控件或是tableView的cell通过一个方法[self performSegueWithIdentifier:@"personInfoVC" sender:person];进行segue跳转并可以传值。
4.在segue跳转前还有一个方法可以把传的值赋给要跳转的界面,就是- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
在添加界面中首先把归档的数据取出来添加进去,然后把新的数据重新归档。
添加代码如下:
// 添加数据 - (IBAction)addOrEditButtonAction:(id)sender { // 添加 MXPerson *person = [[MXPerson alloc] init]; person.name = self.nameTextField.text; person.age = [self.ageTextField.text intValue]; // 首先需要取出归档数据,在往里添加 NSData *data = [NSData dataWithContentsOfFile:@"/Users/tarena/Desktop/persons"]; NSKeyedUnarchiver *unarc = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; NSArray *oldPersonArray = [unarc decodeObjectForKey:@"persons"]; NSMutableArray *newPersonArray = [NSMutableArray arrayWithArray:oldPersonArray]; [newPersonArray addObject:person]; // 添加数据 // 把对象归档 NSMutableData *personData = [NSMutableData data]; NSKeyedArchiver *arc = [[NSKeyedArchiver alloc] initForWritingWithMutableData:personData]; [arc encodeObject:newPersonArray forKey:@"persons"]; [arc finishEncoding]; [personData writeToFile:@"/Users/tarena/Desktop/persons" atomically:YES]; [self.navigationController popViewControllerAnimated:YES]; }
修改:
点击cell后跳到修改界面,然后点击按钮修改。
在跳转时要把当前cell(也就是数组中的某个元素)的数据传到修改界面并显示,修改数据后重新归档。
因为在修改界面要用到第一个界面中数组数据,所以在跳转到修改界面前把自己赋给修改界面的delegate(该代理的类型就是第一个界面),然后进行修改并重新归档。
注意:在跳转时会有多个sender值,在跳转界面要做判断。本例中点击添加,传的sender是nil,点击cell传的sender就是该cell数据。
代码如下:
// 点击cell后跳转到修改界面并传cell的数据 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ MXPerson *person = self.personArray[indexPath.row]; [self performSegueWithIdentifier:@"personInfoVC" sender:person]; } // segue跳转前把数据赋给修改界面 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { MXViewController *personInfoVC = segue.destinationViewController; personInfoVC.person = sender; personInfoVC.delegate = self; } // 添加或修改数据 - (IBAction)addOrEditButtonAction:(id)sender { if (self.person) { // 修改 self.person.name = self.nameTextField.text; self.person.age = [self.ageTextField.text intValue]; [self.delegate savePerson]; } else{ // 添加 } [self.navigationController popViewControllerAnimated:YES]; }
删除:
从归档中删除,然后保存归档
代码如下:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [self.personArray removeObjectAtIndex:indexPath.row]; // 从归档中删除 [self savePerson]; // 保存归档 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } 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 } }
原文:http://www.cnblogs.com/yangmx/p/3561220.html