本文展示如何使用NSUserDefaults類儲存和改變應用程式設定。我們將建立Contact應用程式用於存放使用者指定的圖片和連絡人資訊。
什麼是NSUserDefaults?
NSUserDefaults類用於儲存應用程式設定和屬性以及使用者資料。例如,你可以儲存使用者在應用程式中使用的圖片或預設顏色方案。這些Object Storage Service在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了。
摘自 kmyhy的專欄