iOS Programming NSUserDefaults
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
+initialize:
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。这里是一些能接受的值:
PSTextFieldSpecifier
a labeled text field 标签文字
PSToggleSwitchSpecifier
a labeled toggle switch 开关标签
PSSliderSpecifier
a slider (not labeled) 滑动
PSRadioGroupSpecifier
a list of radio buttons; only one can be selected 一列radio buttons,只有一个可选
PSMultiValueSpecifier
a table view of possibilities; only one can be selected 一个table view 的可能
PSTitleValueSpecifier
a title for formatting
PSGroupSpecifier
a group for formatting
PSChildPaneSpecifier
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 的一个观察者。
iOS Programming NSUserDefaults的更多相关文章
- Head First iOS Programming
内部分享: Head First iOS Programming http://www.slideshare.net/tedzhaoxa/head-first-ios-programming-4606 ...
- iOS Programming Recipe 6: Creating a custom UIView using a Nib
iOS Programming Recipe 6: Creating a custom UIView using a Nib JANUARY 7, 2013 BY MIKETT 12 COMMENTS ...
- iOS Programming Autorotation, Popover Controllers, and Modal View Controllers
iOS Programming Autorotation, Popover Controllers, and Modal View Controllers 自动旋转,Popover 控制器,Moda ...
- iOS Programming Controlling Animations 动画
iOS Programming Controlling Animations 动画 The word "animation" is derived from a Latin wor ...
- iOS Programming UIStoryboard 故事板
iOS Programming UIStoryboard In this chapter, you will use a storyboard instead. Storyboards are a f ...
- iOS Programming Localization 本地化
iOS Programming Localization 本地化 Internationalization is making sure your native cultural informatio ...
- iOS Programming State Restoration 状态存储
iOS Programming State Restoration 状态存储 If iOS ever needs more memory and your application is in the ...
- iOS Programming UISplitViewController
iOS Programming UISplitViewController The iPad, on the other hand, has plenty of screen space to pr ...
- iOS Programming UIWebView 2
iOS Programming UIWebView 1 Instances of UIWebView render web content. UIWebView可以显示web content. In ...
随机推荐
- 网易新闻client(高仿)
近期整理了下自己曾经做过的项目,决定分享出来.本篇所展示的是仿网易新闻client,服务端是在新浪SAE部署着的.所以大家下载后,可直接在手机上看到效果.接下来看效果图: watermark/2/te ...
- 基于FFMPEG SDK流媒体开发1---解码媒体文件流信息
近期项目涉及到流媒体等开发,因为有过开发经验深知其难度所在,没办法仅仅能又一次拾起,最新版的SDK被改的一塌糊涂,只是大体的开发思路都是一样的,看多少书查多少资料都无用,一步一步的编写代码 才是学好的 ...
- 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) D.Dinner Bet 概率DP+排列组合
题目链接:点这里 题意: 1~N标号的球 现在A有C个,B有C个 每次可以随机得到D个不同的球(1~N);问你A或B中的C个球都出现一次的 期望次数 题解: dp[i][j][k]表示 随机出现了i个 ...
- form之action的绝对路径与相对路径(转载)
1.当你的form要提交到你自己的站点之外的URL的时候,就采取绝对路径: <form action="http://www.xxx.yyy:zzzz/mmm/nn/kkk.jsp&q ...
- Delphi的函数指针
不求全面,先留个爪: TNotifyEvent = procedure(Sender: TObject) of object; TMethod = record Code, Data: Pointer ...
- windows安装SVN服务器并设置开机启动
1.安装SVN服务器,到http://subversion.apache.org/packages.html上下载windows版的SVN,并安装,在命令行下运行svn命令,如下所以,则svn服务器安 ...
- YTU 2913: 距离产生美
2913: 距离产生美 时间限制: 1 Sec 内存限制: 128 MB 提交: 152 解决: 133 题目描述 小明和静静是大学同学,毕业后要去两个不同的城市工作.小明要静静做他的女朋友,静静 ...
- 并不对劲的LCT
LCT,是连猫树(link-cat-tree)的缩写.它是树链剖分和splay的结合版本. 由于有很多关于LCT的文章以及这并不是对劲的文章,并不对劲的人并不打算讲得太详细. 推荐:详细的LCT-&g ...
- 【SCOI 2005】 扫雷
[题目链接] 点击打开链接 [算法] 只要第一行第一个数确定了,后面的数也都确定了 递推两遍即可 [代码] #include<bits/stdc++.h> using namespace ...
- tcp/ip网络通讯安全加密方法
tcp/ip网络通讯安全是一个广受关注的话题,现在也有一些基于tcp/ip加密技术标准如SSL,TLS等.但很多时候编写一些简单的网络通讯把这标准加密应用添加进来乎一下子把程序变得复杂了,而实现自己的 ...