本文展示如何使用NSUserDefaults类存储和改变应用程序设置。我们将创建Contact应用程序用于存放用户指定的图片和联系人信息。
什么是NSUserDefaults?
NSUserDefaults类用于保存应用程序设置和属性以及用户数据。例如,你可以存储用户在应用程序中使用的图片或默认颜色方案。这些对象存储在iOS所谓的“defaults系统”中。iOS的defaults系统在整个app中都是可用的,因此存放到defaults系统中的数据也是整个应用程序生命周期中可用的。也就是说,无论用户关闭程序还是关机,在用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:
NSData
NSString
NSNumber
NSDate
NSArray
NSDictionary
如果你想保存其他类型,如UIImage,你应该进行编码(即archive),或者将它转换为NSData、NSNumber或者NSString。
现在,我们将通过一个简单的demo,开始学习如何使用defaults系统。
第 1 步: 创建项目
新建项目。选择View-based Application ,点击 Next。输入项目名称Contact。输入公司标识,Device Family选择iPhone。点击Next。选择文件保存位置,然后点击Create。
第 2 步: 设计界面
在ProjectNavigator的Contact文件夹下,选择ContactViewController.xib。拖入3个UITextFields到画布,如下图所示。拖入一个UIImageView和2个RoundRect Button。
选择第一个TextField,将Placeholder设置为FirstName。将第2个TextField的Placeholder设置为Last Name。将第3个TextField的Placeholder设置为Age,同时将keyboardtype设置为Number Pad。
第1个按钮的text设置为Save,第2个按钮的text设置为ChooseImage。
图片
现在,我们创建连接。点击Editor中间的按钮,显示Assistanteditor。
选择first name文本框,右键(CTRL+左键)拖到interface声明部分,将弹出一个popup窗口,在name中输入firstNameTextField,然后点击connect。
图片
以同样的方式为Lastname、Age文本框和UIImageView创建连接,分别是:lastNameTextField、ageTextField和contactImageView。
对于按钮,我们需要创建Action而不是Outlet。从保存按钮右键拖一条线到interface声明部分,但这次我们要拖在花括号以外。将Connection改为Action(不是Outlet)并在name中输入save。同样,为ChooseImage按钮创建Action连接,name为chooseImage。现在,ContactViewController.h代码将如下所示:
#import <UIKit/UIKit.h>
@interface ContactViewController : UIViewController {
IBOutlet UIImageView *contactImageView;
IBOutlet UITextField *firstNameTextField;
IBOutlet UITextField *lastNameTextField;
IBOutlet UITextField *ageTextField;
}
- (IBAction)save:(id)sender;
- (IBAction)chooseImage:(id)sender;
@end
接下来,点击Build andRun。输入一些文本并退出程序。如果再次打开程序,你回发现你输入的文本仍然存在。这不过iOS的“多任务”特性而已。如果你从多任务栏中删除程序图标,再次启动程序,你会发现你输入的文本不见了。在本文,我们会使用NSUserDefaults保存你输入的信息,哪怕你“真的”退出了程序。这些数据能够在多个会话中存在。
第 3 步: 挑选图片
返回standardEditor模式,以释放出更多的空间。打开ContactViewController.h,加入UIImagePickerControllerDelegate和UINavigationControllerDelegate协议。
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
打开ContactViewController.m,在chooseImage:方法中加入代码:
- (IBAction)chooseImage:(id)sender
{
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
}
首先,我们创建了一个UIImagePickerController,然后将它的delegate设置为self。然后,我们将“允许用户编辑”属性设置为YES,将UIImagePickerController的源类型设置为照片库。最后,弹出UIImagePickerController。
接下来,我们该实现imagepicker的委托方法
#pragma mark - Image Picker Delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
contactImageView.image = image;
[picker dismissModalViewControllerAnimated:YES];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissModalViewControllerAnimated:YES];
}
第一个方法中,我们将contactImageView的image属性设置为用户所选择的图片并解散UIImageViewController。第二个方法中,我们只是解散UIImageViewController。
第 4 步: 保存数据
保存文本使用setObject:forKey方法。key用于指定保存的文本的索引键,当你取出数据时用这个索引键去检索它。如果保存整数,使用setInteger:forKey方法。对于图片的保存我们需要创建NSData实例。
save方法修改如下:
- (IBAction)save:(id)sender
{
// Hide the keyboard
[firstNameTextField resignFirstResponder];
[lastNameTextField resignFirstResponder];
[ageTextField resignFirstResponder];
// Create strings and integer to store the text info
NSString *firstName = [firstNameTextField text];
NSString *lastName = [lastNameTextField text];
int age = [[ageTextField text] integerValue];
// Create instances of NSData
UIImage *contactImage = contactImageView.image;
NSData *imageData = UIImageJPEGRepresentation(contactImage, 100);
// Store the data
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:firstName forKey:@"firstName"];
[defaults setObject:lastName forKey:@"lastname"];
[defaults setInteger:age forKey:@"age"];
[defaults setObject:imageData forKey:@"image"];
[defaults synchronize];
NSLog(@"Data saved");
}
首先,我们将键盘释放。然后创建NSString用于临时保存用户输入的Firstname和Last name文本。对于用户Age文本,我们用一个int保存。对于contactImageView的image,由于不能直接在NSUserDefaults对象中存放UIImage,我们只能使用NSData来储存。然后我们把数据放入NSUserDefaults对象中。最后我们用synchronize方法把数据持久化到standardUserDefaults数据库。
第 5 步: 读取数据
最终我们要读取刚才存储的数据。由于viewDidLoad方法在程序启动时会调用,我们选择在这个方法中进行。在viewDidLoad方法,我们修改为如下所示的代码:
- (void)viewDidLoad
{
// Get the stored data before the view loads
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *firstName = [defaults objectForKey:@"firstName"];
NSString *lastName = [defaults objectForKey:@"lastname"];
int age = [defaults integerForKey:@"age"];
NSString *ageString = [NSString stringWithFormat:@"%i",age];
NSData *imageData = [defaults dataForKey:@"image"];
UIImage *contactImage = [UIImage imageWithData:imageData];
// Update the UI elements with the saved data
firstNameTextField.text = firstName;
lastNameTextField.text = lastName;
ageTextField.text = ageString;
contactImageView.image = contactImage;
[super viewDidLoad];
}
首先,我们调用standardUserDefaults方法获得NSUserDefaults。我们把Firstname和Last name读到了NSString中。由于Age是一个整数,我们把它转变为了字符串——因为我们无法直接把int赋值给TextField的text属性。我们把image对象读入到NSData对象,然后用NSData创建一个UIImage。最后,我们用读到的数据更新UI控件的显示内容。整个程序创建完了,再次点击Buildand Run。输入你的信息并挑选一张图片。从多任务栏中关闭程序,然后再次打开它,所有数据将再次被显示。如果一切正常,我们的demo程序就OK了。