iOS Programming NSUserDefaults,iosnsuserdefaults


iOS Programming NSUserDefaults,iosnsuserdefaults

iOS Programming NSUserDefaults 

When you start an app for the first time, it uses its factory settings. As you use it, a good app learns your preferences. Where are your preferences stored? Inside each app bundle there is a plist that holds the user's preferences. As a developer, you will access this plist using the NSUserDefaults class. The preferences plist for your app can also be edited by the Settings app. To allow this, you create a settings bundle inside your app.

當你第一次開始你的app時,你使用它的工廠設定。當你使用它時,一個好的app 會學習你的preferences.你的preferences 存在哪了呢?在每個app bundle中都有一個plist 保持了user的preference.作為一個developer,你可以通過使用NSUserDefaults類。preferences plist 你的app能夠通過setting app 編輯。為了允許這個,你需要建立一個setting bundle 在你的app內。

1 NSUserDefaults

The set of defaults for a user is a collection of key-value pairs. The key is the name of the default, and the value is some data that represents what the user prefers for that key.You ask the shared user defaults object for the value of that key – not unlike getting an object from a dictionary:

對一個使用者的defaults 的設定是一個key-value pairs 容器。key 是default的名字,而value是代表餓了使用者喜歡什麼的資料。你詢問shared user defaults 對象為了那個key 的value,很像從一個字典中擷取對象。

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSString *greeting = [defaults objectForKey:@"FavoriteGreeting"];

If the user expresses a preference, you can set the value for that key:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setObject:@"Hello" forKey:@"FavoriteGreeting"];

This value will automatically be stored to the app's preferences plist. Thus, the value must be a plist type: NSArray, NSDictionary, NSString, NSData, NSDate, or NSNumber. If you want to store a non-plist type to the user defaults, you will need to convert it to a plist. Often this is accomplished by archiving the object (or objects) into an NSData, which is a plist.

這些值自動的存入app的preference plist.因此這個value必須是plist type:NSArray,NSDictionary,NSString,NSData,NSDate,or NSNumber.如果你是存的一個non-plist,你需要把它轉換為plist。通常這會存檔一個對象為NSData。

What if you ask for the value of a preference that has not been set by the user? NSUserDefaults will return the factory settings, the "default default," if you will. These are not stored on the file system, so you need to tell the shared instance of NSUserDefaults what the factory settings are every time your app launches. And you need to do it early in the launch process – before any of your classes try to read the defaults. Typically you will override +initialize on your app delegate:

如果你詢問一個preference的值還沒有被設定?NSUserDefaults將會返回factory settings ,the "default default",如果你樂意。這些沒有儲存到檔案系統中,所以你需要告訴NSUserDefaults 的shared instance  在你的app 每次啟動時要設定什麼factory settings .你需要做這些在啟動程式的早期:在你的類別檢視讀取defaults之前。一般你回重+initialize 在你的app delegate上。

+ (void)initialize


NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSDictionary *factorySettings = @{@"FavoriteGreeting": @"Hey!",

@"HoursBetweenMothershipConnection : @2};

[defaults registerDefaults:factorySettings];


The class method initialize is called automatically by the Objective-C runtime before the first

instance of that class is created.

這個類方法initialize 在那個類被建立的Objective -C 已耗用時間自動的被調用。

1.1 Register the factory settings

註冊factory Settings

At launch time, the first thing that will happen is the registering of the factory settings. It is considered good style to declare your preference keys as global constants.

啟動時,將發生的第一件事就是factory settings 的註冊。聲明你的preference keys 為一個global  constants 是一種好的方式。Open BNRAppDelegate.h and declare two constant global variables:

extern NSString * const BNRNextItemValuePrefsKey;

extern NSString * const BNRNextItemNamePrefsKey;

In BNRAppDelegate.m, define those global variables and use them to register the factory defaults in


NSString * const BNRNextItemValuePrefsKey = @"NextItemValue";

NSString * const BNRNextItemNamePrefsKey = @"NextItemName";


@implementation BNRAppDelegate

+ (void)initialize


NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSDictionary *factorySettings = @{BNRNextItemValuePrefsKey: @75,

BNRNextItemNamePrefsKey: @"Coffee Cup"};

[defaults registerDefaults:factorySettings];



1.2 Read a preference      讀取一個preference

When you create a new item in BNRItemStore.m, use the default values. Be sure to import BNRAppDelegate.h at the top of BNRItemStore.m so that the compiler knows about BNRNextItemValuePrefsKey.


NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

item.valueInDollars = [defaults integerForKey:BNRNextItemValuePrefsKey];

item.itemName = [defaults objectForKey:BNRNextItemNamePrefsKey];

// Just for fun, list out all the defaults
NSLog(@"defaults = %@", [defaults dictionaryRepresentation]);

Notice the method integerForKey:. It is there as a convenience. It is equivalent to:

item.valueInDollars = [[defaults objectForKey:BNRNextItemValuePrefsKey] intValue];

There are also convenience methods for setting and getting float, double, BOOL, and NSURL values.

1.3 Change a preference

You could create a view controller for editing these preferences. Or, you could create a settings bundle for setting these preferences. Or, you can just try to guess the user's preferences from their actions. For example, if the user sets the value of an item to $100, that may be a good indication that the next item might also be $100. For this exercise, you will do that.

你可以建立一個view controller 來編輯這些preferences.或者,你能建立settings  bundle 來設定這些preferences.或者你僅僅視圖猜測使用者的preferences 從他們的actions。例如,一個使用者佈建一個item的value是100,那麼這是一個很好的indication ,next item 可能也是100。

Open BNRDetailViewController.m and edit the viewWillDisappear: method.


int newValue = [self.valueField.text intValue];

// Is it changed?

if (newValue != item.valueInDollars) {

// Put it in the item item.valueInDollars = newValue;

// Store it as the default value for the next item

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setInteger:newValue    forKey:BNRNextItemValuePrefsKey];

item.valueInDollars = [self.valueField.text intValue];



Import BNRAppDelegate.h so that the compiler knows about the BNRNextItemValuePrefsKey constant.

Sometimes you will give the user a button that says "Restore factory default", which will remove some defaults from the app's preferences plist.

To remove key-value pairs from your app's preferences plist, NSUserDefaults has a removeObjectForKey: method.

有時候你提供給使用者一個button 說重新設定factory default,這將移除所有的default在你的app的preferences plist.移除所有的key-value pairs 從你的app's preferences plist,NSUserDefaults 有一個removeObjectForKey方法。


2 Settings Bundle 

Now you are going to create a settings bundle so that the NextItemName preference can be changed from "Coffee Cup" to whatever string the user desires.

現在你將建立一個settings bundle 這樣NextItemName preference 能從"Cofffee Cup"到任何使用者需要的資料。

These days many designers consider settings bundles to be distasteful and most apps do not include a settings bundle. That said, many apps do have settings bundles, so it is a good idea to know how to make them.

這些天,許多designers 認為setting bundles 為不好的,許多apps 不包括setting bundles .也就是許多apps 有settings bundles ,所以知道怎麼用她是有用的。

The bundle is just a directory that holds a plist that describes what controls should appear in this view and what default each control is manipulating. 

bundle 僅僅是擁有了一個plist表示了什麼控制應該出現在這個view和每個控制預設的操作是什麼的一個目錄而已。

You will pull the user visible strings (like the label "Default Item Name" in
Figure 26.1) into a strings file that is localized for the user. Those strings files will also be in the settings bundle.

你將把user visible strings 放進一個Strings  file用來使用者本地化。這些Strings files 也將在settings bundle.

To create a settings bundle inside your app, open Xcode's File menu and choose New → File.... Under the iOS Resources pane, choose Settings Bundle


Accept the default name. Notice that a directory called Settings.bundle has been created in your project directory. It has a Root.plist file and an en.lprog subdirectory.

1.1 Editing the Root.plist

The Root.plist describes what controls will appear in your app's settings pane. It contains an array of dictionaries; each dictionary represents one view (typically a control) that will appear on the pane. Every dictionary must have Type key. Here are the acceptable values for Type:

Root.plist表述了什麼控制將顯示到你的app's setting pane。它包含了一列dictionaries;每個dictionary 代表了一個view將顯示在pane上的。每個dictionary 必須有一個Type key。這裡是一些能接受的值:


a labeled text field 標籤文字


a labeled toggle switch 開關標籤


a slider (not labeled) 滑動 


a list of radio buttons; only one can be selected 一列radio buttons,只有一個可選


a table view of possibilities; only one can be selected 一個table view 的可能


a title for formatting


a group for formatting


lets you move some preferences onto a child pane

讓你移動一些preferences 到child pane.

Notice that you have been laying out a user interface using a plist file. When you create a settings bundle, you are not writing any executable code, and you are not creating any view controllers or other objects that you control. The Settings application will read your application's Root.plist and will construct its own view controllers based on the contents of the plist file.

注意到你已經laying out 一個user interface用一個plist file.當你建立一個setting bundle時,你沒有寫任何可執行檔代碼,你也沒有建立然任何view controller 或者是你控制的其他對象。setting application 會讀取你應用的root.plist並構建自己的view controller 基於plist file的內容。

2.2 Localized Root.strings

Inside your settings bundle is an en.lproj which will hold your English strings. You can delete all the key-value pairs and give the title for your text field:

在你的setting bundle是一個en.lproj,它將保持你的English strings.你可以刪除所有的key-value pairs 並給定你的text field 的title。

"NextItemName" = "Default Item Name";

One final point: when your defaults are changed (by your own app or the Settings app) an NSUserDefaultsDidChangeNotification will get posted to your application. If you want to respond to changes in the Settings app immediately, register as an observer of this notification.

最後一點是:當你的defaults 發生改變時,NSUserDefaultsDidChangeNotification 將推送給application。如果你想及時的響應setting app 立刻的,註冊成為這個notification 的一個觀察者。




如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

Tags Index: