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 ...
随机推荐
- DLR之 ExpandoObject和DynamicObject的使用演示样例
ExpandoObject :动态的增删一个对象的属性,在低层库(比如ORM)中非常实用.因为ExpandoObject实现了IDictionay<string, object>接口,常见 ...
- MD5加密解密帮助类
using System; using System.Security.Cryptography; using System.Text; namespace Maticsoft.DBUtility { ...
- SpringMVC_架构 --跟海涛学SpringMVC(学习笔记)
重点: 1.工作流程及实现原理 2.配置及使用方法 3.共同函数 前言 1.2.模型: 1.2.1.此处模型使用JavaBean,可能造成JavaBean组件类很庞大,一般现在项目都是采用三层架构,而 ...
- linux 监控进程所消耗的资源(内存),达到阈值(绝对值、相对值)后,将其杀死
监控某个python进程是否存在,如不存在则启动 #!/bin/bashwhile [ 1 ]do #打印出当前的jboss进程:grep jboss查询的jboss进程,grep -v " ...
- div内鼠标坐标位置及绝对和相对坐标获取
JQuery 获得div绝对,相对位置的坐标方法 1 2 3 4 5 6 获取页面某一元素的绝对X,Y坐标 var X = $('#DivID').offset().top; var Y = $( ...
- python 判断是否为有效域名
import re pattern = re.compile( r'^(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|' r'([a-zA-Z]{1}[0-9]{1}) ...
- 创建cell的三种方式
方式一 注册cell -> 无需为cell绑定标识符 [使用UIViewController完成!] l 1> static NSString * const ID = @"c ...
- 《编程珠玑,字字珠玑》读书笔记完结篇——AVL树
写在最前面的 手贱翻开了<珠玑>的最后几章,所以这一篇更多是关于13.14.15章的内容.这篇文章的主要内容是“AVL树”,即平衡树,比红黑树低一个等次.捣乱真惹不起红黑树,情况很复杂:而 ...
- bzoj 3781 小B的询问 —— 莫队
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3781 就是莫队,左端点分块排序,块内按右端点排序,然后直接做即可. 代码如下: #inclu ...
- .NET修改配置文件
首先说明,本文参考了这个帖子http://www.cnblogs.com/henw/archive/2012/01/31/2333783.html,进行了一些补充 简要说来两种方法,一是把config ...