iPhone允许应用程序将自定义首选项添加到Settings应用程序中,开发者也可以以编程的方式指定这些设置,但添加到Settings应用程序的方式会提供一个友好的GUI。自定义首选项支持多种多样的数据交互风格,包括文本、密码、开关、滑块、以及二级选择页面。但这里应注意避免敏感信息。
IOS应用程序存储信息的方式主要有三种:
1. 单例类NSUserDefaults:NSUserDefaults类的工作原理类似于NSDictionary,所有首选项都以键/值对的方式存储在NSUserDefaults单例中。
2. 设置束(Settings Bundle):提供了一个通过iOS应用程序Settings对应用程序进行配置的接口。
3. 直接访问文件系统:能够读取属于当前应用程序的iOS文件系统部分的文件。常见的如数据库文件。
设置束也是对一个plist文件进行编辑,它的优点在于,可以通过Xcode plist编辑器来操作,无需额外编写代码,只需要在编辑器里定义要存储的数据及其键即可。
创建设置首选项菜单的步骤如下:
1.New File…,选择Resource,选择Settings Bundle,创建一个Settings.bundle文件,默认名称即可。建议添加到Supporting Files分组里。
2.打开项目窗口的Settings.bundle项,应该看到Root.plist和en.lproj文件,其中en.lproj是关于设置束国际化的文件,暂时不考虑。打开Root.plist文件,这个文件本质上就是字典,是以键值对来存储和操作的。
3.Root.plist文件中的节点的类型有:Boolean、Data、Date、Number、String(基本的类型);Dictionary和Array(能够包含其他节点的类型)。
4.在Root.plist中设置属性列表的时候要遵循特定格式。我们能够操作的地方在Preference Items数组(类型为Array)里,请删除或修改此项里面的默认项,如果有的话。正常情况下应爱是有四个子项的分别为分组、输入框、开关、滑块(我的Xcode版本为6.3.2)。但请注意,Preference Items项的(直接)子项只能够是Dictionary类型的。
设置束中的文件Root.plist决定了应用程序首选项如何呈现在应用程序Settings中。有7种类型的首选项,分别为:
Text Field:文本框。键为PSTextFieldSpecifier,可编辑的文本字符串。常用于保存用户自定义的信息,如昵称等。
Title:标题。键为PSTitleValueSpecifier,只读文本字符串。常用于显示不变的信息,如版本信息。
Toggle Switch:开关。键为PSToggleSwitchSpecifier,开关按钮。
Slider:滑块。键为PSSliderSpecifier,取值位于特定范围内的滑块。
Multi value:多值。键为PSMultiValueSpecifier,下拉式列表。
Group:编组。键为PSGroupSpecifier,首选项逻辑编组的标题。常用于设置项的分组。
Child Pane:子窗格。键为PSChildPaneSpecifier,子首选项页。常用于选项比较多的选择菜单。
小窍门:
当前Xcode版本中,可以快速创建各菜单项。单击菜单项的键列,会弹出快捷创建项的菜单。选择想要的类型即可自动创建部分键值对,然后略做修改即可。
下面开始介绍各种菜单的用法:
1.Text Field:文本框。文本框可选的键有如下几个:
Autocapitalization Style:自动大写。有四个值: None(无)、Sentences(句子首字母大写)、Words(单词首字母大写)、All Characters(所有字母大写)。
Autocorrection Style:自动纠正拼写,如果开启,你输入一个不存在的单词,系统会划红线提示。有三个值:Default(默认)、No Autocorrection(不自动纠正)、Autocorrection(自动纠正)。
Default Value:默认值。注意,包括其他菜单的Default Value,只是默认的值,一旦用户直接或间接更改,Default Value不再作用,此后显示或获取的都只是用户最新设置的值。
Identifier:设置项标示,用于在程序中获取设置项的值的键Key。
Keyboard Type:键盘样式。有五个值:Alphabet(字母表,默认)、Numbers and Punctuation(数字和标点符号)、Number Pad(数字面板)、URL(比Alphabet多出了.com等域名后缀)、Email Address(比Alphabet多出了“@”符号)。
Text Field Is Secure:是否为安全文本(密码)。如果设置为YES,则内容以圆点符号出现。
Title:提示文本。用于在你的文本框前提示文本框的内容。
Type:设置文本框的话,这个只能选Text Field。
设置完成后,你的文本框项可能是这样的:
2.Title:标题。标题可选的键有如下几个:
Default Value:默认值。这个会显示在设置项的右方,灰色字体。
Identifier、Title同上。
Titles和Values:用于指定Default Value的可选值,如分别在Titles和Values下各设置5个值,这时可以指定Default Value为Values里的一个值,这时会在设置里显示Titles里相应的项。Titles和Values中,显示时只显示对应的Title,取值时只获取到对应的Value。注意通过代码修改这个Title对应的Value时,要确认值包含在Values。 注意这里的Titles和Values项,不会在Settings页面中生成一个子级设置页面供选择Value。
Type:设置标题的话,这个只能选Title。
设置完成后,你的标题项可能是这样的:
3.Toggle Switch:开关按钮。开关项可选的键有如下几个:
Default Value:默认值。
Identifier、Title同上。
Type:设置开关的话,这个只能选Toggle Switch。
Value for ON和Value for OFF:设置开关状态对应的值。
设置完成后,你的开关项可能是这样的:
4.Slider:滑块。滑块项可选的键有如下几个:
Default Value、Identifier同上。
Minimum Value、Maximum Value:最小值和最大值。
Min Value Image Filename、Max Value Image Filename:在滑动条左右显示的图片。图片大小必须为21*21,并且要放在Settings.bundle包内(在Finder里显示包内容,然后粘贴)。
Type:设置滑块的话,这个只能选Slider。
设置完成后,你的滑块项可能是这样的:
5.Multi value:多值。多值项可选的键有如下几个:
Default Value:默认值。
Identifier、Title同上。
Type:设置开关的话,这个只能选Multi Value。
Titles和Values:基本同上,但这个多值的Titles和Values会在Settings页面中生成一个子级设置页面供选择Value。
6.Group:分组。
如果你要在首选项里面添加分组的话,那么请使用Group:建立一个Preference Items的子项(如:“Item 0”),类型为“Dictionary”,并且包含两个类型为“String”子项,名称分别为:“Type”和“Title”,值分别为:“Group”和“GroupName”(GroupName是你自定义的组名,可以任意的名字)。注意,分组直到遇到下一个同级的指示分组的项结束,或者遇到同级最后一项时结束。
设置完成后,你的fe项可能是这样的:
7.Child Pane:子窗格。这个可以定义一个二级菜单,可选的键有三个:
Type:创建子窗格必选Child Pane。
Title:标题,在应用程序首选项菜单中父页显示的标题。
Filename:指定子窗格菜单对应的plist文件,类似于默认的Root.plist。这个项填写时不要带后缀名。另外这个文件要和Root.plist文件放到一起。右键Root.plist文件,选择Show in Finder。然后在Finder窗口中右键Root.plist文件选择复制。默认会复制到当前目录下一个Root.plist的副本。接着修改一个有意义的名字即可(这里改成Child.plist)。然后编辑Child.plist文件,右键Child.plist的根项目,选择Property List Type里的iPhone Settings plist。这样再编辑这个文件时,就会有自动提示了。
Child.plist文件的StringsTable这一项可有可无,建议保留,并修改键为Strings Filename(和Root.plist中相同),值为其文件名,这里是Child,不要带文件后缀。
设计设置菜单项就这么多吧。这些Setting的数据将存储在NSUserDefaults中StandardDefaults当中,每个设置对应的identifier就是Key。然后只需要按NSUserDefaults的操作方式操作设置项就行了。
下面贴出一段获取设置项的代码:
1 - (void)readingSettingsPreference 2 { 3 //获取Settings.bundle路径 4 NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"]; 5 6 if(!settingsBundle) 7 { 8 NSLog(@"找不到Settings.bundle文件"); 9 return; 10 } 11 12 //读取Settings.bundle里面的配置信息 13 NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]]; 14 NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"]; 15 NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]]; 16 17 for(NSDictionary *prefSpecification in preferences) 18 { 19 NSString *key = [prefSpecification objectForKey:@"Key"]; 20 if(key) 21 { 22 [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key]; 23 } 24 } 25 26 [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister]; 27 28 [[NSUserDefaults standardUserDefaults] synchronize]; 29 30 //TODO:读取指定数据 31 32 }