使用Settings Bundle为程序添加设置项

创建一个Demo来学习一个Setting Bundle为程序存储设置项

Settings Bundle是在自己的程序中建立的一组文件,利用它可以告诉设备中的Settings程序我们写的程序有哪些设置项。用户在Settings程序中设置好相关相关选项后回到我们自己的程序,自己的程序中的对应项也会发生相应的变化。

在iOS程序中,用户默认项,即上面所说的设置项,是用NSUserDefaults类实现的。在NSUserDefaults类中使用关键字来读取和存储设置项的具体数据,就像NSDictionary类一样,不同的是,NSUserDefaults类的数据是存储在文件系统中的,而不是作为一个对象实例放在内存中。

在这篇文章中,我们将创建一个程序,为它添加和配置Settings Bundle,之后可以在Settings程序中显示和配置相关选项。在Settings Bundle中使用plist文件来定义程序中允许的设置项,Settings程序会自动建立接口。Settings Bundle中的plist文件必须遵循特定的格式,不过Xcode会帮助我们遵循这种格式。

实现步骤:

1、首先下载初始代码。http://www.oschina.net/code/snippet_164134_10458

由于我们的重点是Settings Bundle的使用,那么建立工程、实现页面跳转等等就不详细说明了。

2、解压Settings Bundle Test.zip,使用Xcode 4.3打开此工程,先打开FirstViewController.xib,使用IB向其中添加控件,如下图:

然后为这些标签向FirstViewController.h中建立Outlet映射:

3、打开MoreViewController.xib,向其中添加控件,如下:

然后,向MoreViewController.h中,为右边的两个Label以及UISlider与UISWitch控件创建Outlet映射,为UISlider与UISWitch控件添加Action映射:

然后在Attribute Insepector中设置UISlider控件最小值、最大值和默认值分别是0、10和5:

将准备好的两张图片添加到工程中,在Attribute Insepector中设置UISlider控件的Min Image与Max Image:

4、接下来,为程序建立Settings Bundle。依次选择File — New — File…,找到Settings Bundle:

单击Next,设置好名称和分组:

然后单击Create,则创建了Settings.bundle。

5、展开Settings.bundle,其中包含一个Root.plist。Settings程序中的显示项就是从Root.plist中获取的。

单击Root.plist以打开它,在空白处单击,选中Show Raw Keys/Values:

接下来,我们展开PreferenceSpecifiers那一项,删除除了Group之外的其他项。

PreferenceSpecifiers这个对应于刚打开Settings程序时第一页中该应用程序的一个标签,如果此时运行程序,然后在模拟器返回桌面,再打开Settings程序,则其中会出现Settings Bundle Test这一项:

上图中的Settings Bundle Test这一项就可以理解为是从PreferenceSpecifiers获取的。

6、展开PreferenceSpecifiers这一项,先向其中添加三行,每一行的设置如下:

此时运行程序,在Settings程序中单击上图中的Settings Bundle Test那一项,出现的页面如下图:

   

在Root.plist文件中,Item 0那一项的类型是PSGroupSpecifier,它表示一个分组,则它下面的每Item 1到Item 3都是在这一组,直到下一个PSGroupSpecifier出现。

Item 1与Item 2都是PSTextFieldSpecifier类型的,它们都是文本框,可以通过为其添加子项限制这些文本框的输入。

Item 3是一个多选框,可供选择的值是由Titles与Values决定的,Titles与Values这两项内容是一样的,但是缺一不可。

7、之后,再向其中添加Item 4到Item 7,如下图:

再运行程序,打开Settings程序看看:

   

8、之后,我们实现在上面左图的下方出现一项“更多设置”,单击此项跳转到新的页面。先创建一个plist文件,名称为MoreSettings.plist,创建方法就不说了吧,参考http://my.oschina.net/plumsoft/blog/42084第二步。注意现在只是创建到工程中而不是Settings.bundle中,想要加到Settings.bundle中还要其他操作,稍后详解。

右击Settings.bundle,选择Show in Finder:

然后在Finder中右击Settings.bundle,选择“显示包含内容”:

在打开的地方将MoreSettings.plist以及上面用到的两张图片拷贝进去。

9、编辑Settings.bundle中的MoreSettings.plist内容如下:

保存后,在Root.plist添加一行:

注意,Item 8的类型是通过选择其子选项Type的类型改变的。

此时运行程序,Settings程序如下:

   

10、接下来都是代码了。

10.1 在ViewController.h中添加代码:

#define kUserName @"username" #define kPassWord @"password" #define kGender @"gender" #define kFavouriteColor @"favouritecolor" #define kFavouriteSeason @"favouriteseason" #define kFavouriteSport @"favouritesport" #define kTheSlider @"theslider" #define kTheSwitch @"theswitch"

10.2 在FirstViewController.h与MoreViewController.h中分别声明一个方法,名为

- (void)refreshFields;

在FirstViewController.m中添加代码如下:

- (void)refreshFields {     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     self.userNameLabel.text = [defaults objectForKey:kUserName];     self.passWordLabel.text = [defaults objectForKey:kPassWord];     self.genderLabel.text = [defaults objectForKey:kGender];     self.colorLabel.text = [defaults objectForKey:kFavouriteColor];     self.seasonLabel.text = [defaults objectForKey:kFavouriteSeason];     self.sportLabel.text = [defaults objectForKey:kFavouriteSport]; }

在MoreViewController.m中添加代码如下:

- (void)refreshFields {     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     self.theSwitch.on = [defaults boolForKey:kTheSwitch];     self.slider.value = [defaults floatForKey:kTheSlider];     self.sliderValueLabel.text = [[defaults objectForKey:kTheSlider]stringValue]; }

10.3 实现MoreViewController.m中的sliderTapped与switchTapped方法如下:

- (IBAction)sliderTapped:(id)sender {     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     [defaults setFloat:self.slider.value forKey:kTheSlider];     self.sliderValueLabel.text = [[defaults objectForKey:kTheSlider] stringValue];     [defaults synchronize]; } - (IBAction)switchTapped:(id)sender {     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     [defaults setBool:self.theSwitch.on forKey:kTheSwitch];     [defaults synchronize]; }

10.4 在FirstViewController.m与MoreViewController.m中@end之前都添加代码:

- (void)applicationWillEnterForeground:(NSNotification *)notification {     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];     [defaults synchronize];     [self refreshFields]; }

10.5 在FirstViewController.m与MoreViewController.m的viewDidLoad方法中都添加代码:

[self refreshFields]; UIApplication *app = [UIApplication sharedApplication]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:app];

10.6 在FirstViewController.m与MoreViewController.m中的ViewDidUnload方法中都添加代码:

[[NSNotificationCenter defaultCenter] removeObserver:self];

11.7 在ViewController.m的viewDidLoad方法中的[super viewDidLoad];之前添加代码:

//注册默认项 NSDictionary *defaults = [NSDictionary dictionaryWithObjectsAndKeys:                           [NSNumber numberWithBool:YES], kTheSwitch,                           [NSNumber numberWithFloat:5.0], kTheSlider,                           nil]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];

11、运行,那么Settings Bundle Test程序中的数据将会随着Settings程序中的选项改变而改变,反过来也是。

例如,在Settings程序中设置如下:

   

返回Settings Bundle Test程序,显示如下:

   

不过,第一次运行程序时,单击“更多设置”按钮,Slider与Switch是变形的,然后才会显示正确的值:

真是好事多磨啊。

刚运行程序,第一次单击“更多设置”按钮就会出现上图情况。猜想是因为刚开始ViewController中的moreViewController为空,在页面跳转时才创建它。为此,试试在ViewController.m的viewDidLoad方法的最后一条语句之前添加代码:

self.moreViewController = [[MoreViewController alloc] initWithNibName:@"MoreViewController" bundle:nil];  self.moreViewController.viewController = self;

再运行试试,还是不行。那估计是跟页面跳转时的动态效果有关了。再把ViewController.m的switchViews方法修改如下:

- (void)switchViews {     if (self.moreViewController.view.superview == nil) {          if (self.moreViewController == nil) {              self.moreViewController = [[MoreViewController alloc] initWithNibName:@"MoreViewController" bundle:nil];              self.moreViewController.viewController = self;         }     } else {          if (self.firstViewController == nil) {              self.firstViewController = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];             self.firstViewController.viewController = self;         }      }     [UIView beginAnimations:@"View Flip" context:nil];      [UIView setAnimationDuration:0.80];      [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];     if (self.moreViewController.view.superview == nil) {          [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];          [self.firstViewController.view removeFromSuperview];         [self.view insertSubview:self.moreViewController.view atIndex:0];      } else {          [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];          [self.moreViewController.view removeFromSuperview];          [self.view insertSubview:self.firstViewController.view atIndex:0];      }      [UIView commitAnimations];  }

再运行,问题总算解决了。

最终代码:http://www.oschina.net/code/snippet_164134_10484


-------------------------------------------------------------------------------------

另外一个demo实现步骤:

1.创建一个Utility Application。

2.同样创建Settings Bundle文件。

3.点击Root.plist->showRowKeys/Values,看看对应的每个key值,后面在代码预定义的时候要写的key跟这个要一模一样的,NSUserDefault中自动创建的文件,必须要等setting或者view中相应的值改了以后才能产生一个key/value记录。

4.修改MainViewController中的代码

MainViewController.h:

#import "DXWFlipsideViewController.h"  @interface DXWMainViewController : UIViewController <DXWFlipsideViewControllerDelegate>  - (IBAction)showInfo:(id)sender; @property (retain, nonatomic) IBOutletCollection(UILabel) NSArray *labels; @property (retain, nonatomic) IBOutlet UISwitch *switchButton; - (IBAction)change:(id)sender;  @end


MainViewController.m:

#import "DXWMainViewController.h"  @interface DXWMainViewController ()  @end  @implementation DXWMainViewController  -(void)viewWillAppear:(BOOL)animated {     [self changeData]; }  -(void)changeData {     NSUserDefaults *usr = [NSUserDefaults standardUserDefaults];     NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"ding",@"name",@YES,@"switch",@0.4,@"slider",nil];     //在当前的userDeafults注册一个     [usr registerDefaults:dic];     ((UILabel *)self.labels[0]).text = [usr objectForKey:@"name"];     ((UILabel *)self.labels[1]).text = [usr boolForKey:@"switch"]?@"开":@"关";     ((UILabel *)self.labels[2]).text = [NSString stringWithFormat:@"%f",[usr floatForKey:@"slider"]];     self.switchButton.on = [usr boolForKey:@"switch"];          //都要写入一下     [usr synchronize]; }  - (void)viewDidLoad {     [super viewDidLoad]; 	UIApplication *app = [UIApplication sharedApplication];     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeData) name:UIApplicationWillEnterForegroundNotification object:app]; }   #pragma mark - Flipside View  - (void)flipsideViewControllerDidFinish:(DXWFlipsideViewController *)controller {     [self dismissViewControllerAnimated:YES completion:nil]; }  - (IBAction)showInfo:(id)sender {         DXWFlipsideViewController *controller = [[[DXWFlipsideViewController alloc] initWithNibName:@"DXWFlipsideViewController" bundle:nil] autorelease];     controller.delegate = self;     controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;     [self presentViewController:controller animated:YES completion:nil]; }  - (void)dealloc {     [_labels release];     [_switchButton release];     [super dealloc]; } - (IBAction)change:(id)sender {     UISwitch *switchButton = sender;     NSUserDefaults *user = [NSUserDefaults standardUserDefaults];     [user setBool:switchButton.on forKey:@"switch"];     [user synchronize];     ((UILabel *)self.labels[1]).text = [user boolForKey:@"switch"]?@"开":@"关"; } @end





















本文转蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366406,如需转载请自行联系原作者


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Netty自娱自乐之协议栈设计

---恢复内容开始--- 俺工作已经一年又6个月了&#xff0c;想想过的真快&#xff0c;每天写业务&#xff0c;写业务&#xff0c;写业务......。然后就是祈祷着&#xff0c;这次上线不要出现线上bug。继续这每天无聊的增删改查&#xff0c;学习学习一下自己感兴趣的事&#xff0c…

C++包扩展_利用 MATLAB Coder 将M代码生成C/C++代码

利用MATLAB Coder将MATLAB代码生成C/C代码​mp.weixin.qq.comMATLAB Coder 可以将MATLAB代码生成工程中常用的嵌入式或其他硬件平台的C或者C代码。使用者可以在MATLAB中进行验证&#xff0c;然后将生成后的代码集合到工程中。集合的方式可以是源码&#xff0c;静态库和动态库。…

linux 进程通信机制,linux的进程通信机制小结

linux向应用软件提供下列进程间通信手段&#xff1a;####第一类通信方式&#xff1a;只能用于父进程与子进程之间&#xff0c;或者两个兄递进程之间。>管道Pipe>信号Signal>跟踪Trace管道&#xff1a;由父进程来建立。管道两端的进程各自都将该管道视作一个文件。一个…

阿里云胡晓明:数据智能将为城市生活带来真正价值

8月30日&#xff0c;在2017全球&#xff08;上海&#xff09;人工智能创新峰会-世界人工智能城市规划大会上&#xff0c;阿里巴巴集团资深副总裁、阿里云总裁胡晓明作《通往智能之路》主题演讲&#xff0c;指出数据智能将从交通、医疗、城市治理等方面影响城市生活&#xff0c;…

【iCore1S 双核心板_FPGA】例程十二:基于单口RAM的ARM+FPGA数据存取实验

实验现象&#xff1a; 核心代码&#xff1a; module single_port_ram(input CLK_12M,input WR,input RD,input CS0,inout [15:0]DB,input [24:16]A,output FPGA_LEDR,output FPGA_LEDG,output FPGA_LEDB); //----------------------------pll-------------------------------//…

curl post https_Linux命令cURL详解,并实现文件定时上传到ftp服务器的程序

前言前段时间群里讨论&#xff0c;想实现某个文件定时上传到服务器要怎么来实现。我记得之前做过 一个项目&#xff1a;为高通的iot模组编写FOTA功能&#xff1a;实现模组可以远程下载升级镜像包&#xff0c;实现版本升级功能。并当时使用的一个超级强大的工具cURL。心血来潮&a…

linux系统页面缓存,Linux缓存机制之页缓存

内核采用一种通用的地址空间方案&#xff0c;来建立缓存数据与其来源之间的关联。1) 内存中的页分配到每个地址空间。这些页的内容可以由用户进程或内核本身使用各式各样的方法操作。这些数据表示了缓存中的内容&#xff1b;2) 后备存储器struct backing_dev_info指定了填充地…

十月百度,阿里巴巴,迅雷搜狗最新面试七十题(更新至10.17)

十月百度&#xff0c;阿里巴巴&#xff0c;迅雷搜狗最新面试十一题 引言 当即早已进入10月份&#xff0c;十一过后&#xff0c;招聘&#xff0c;笔试&#xff0c;面试&#xff0c;求职渐趋火热。而在这一系列过程背后浮出的各大IT公司的笔试/面试题则蕴含着诸多思想与设计&…

fasttext 文本分类_4种常见的NLP实践思路【特征提取+分类模型】

越来越多的人选择参加算法赛事&#xff0c;为了提升项目实践能力&#xff0c;同时也希望能拿到好的成绩增加履历的丰富度。期望如此美好&#xff0c;现实却是&#xff1a;看完赛题&#xff0c;一点思路都木有。那么&#xff0c;当我们拿到一个算法赛题后&#xff0c;如何破题&a…

Angular4学习笔记(六)- Input和Output

概述 Angular中的输入输出是通过注解Input和Output来标识&#xff0c;它位于组件控制器的属性上方。 输入输出针对的对象是父子组件。 演示 Input 新建项目connInComponents:ng new connInComponents.新增组件stock:ng g component stock.在stock.component.ts中新增属性stockN…

Python 常见加密方式和实现

Python 加密与解密小结 这篇文章主要介绍了Python 加密与解密,使用base64或pycrypto模块 前言 据记载&#xff0c;公元前400年&#xff0c;古希腊人发明了置换密码。1881年世界上的第一个电话保密专利出现。在第二次世界大战期间&#xff0c;德国军方启用“恩尼格玛”密码机…

jenkins日志乱码linux,Jenkins控制台中乱码问题解决

由于服务器环境及应用层各版本的不同、编码方式的不同因此会有很多种情况会出现乱码问题。由于Jenkins中的job运行的是独立的一个shell环境&#xff0c;许多的环境变量与服务器中是不一样的&#xff0c;因此在job中执行的命令也就会有所差异。因此可以在job中执行env命令&#…

windows商店_Windows记事本应用现在可以从Microsoft Store中获得

早在2019年8月&#xff0c;微软就宣布将把人们最常用的Windows记事本应用搬到应用商店&#xff0c;让这款深受用户喜爱的应用更新速度更快、响应更灵敏。12月晚些时候&#xff0c;微软却放弃了这一计划&#xff0c;也没有给出太多理由。但现在&#xff0c;这一计划已经完成&…

jmeter 压测duobbo接口,施压客户端自己把自己压死了

jmeter 压测duobbo接口&#xff0c;jmeter代码不合理&#xff0c;导致每执行一次请求&#xff0c;会调用一次消耗内存的实例化。导致越压越慢&#xff0c;请求发不出去。这个时候需要考虑修改代码了。 截图中&#xff0c;tps越来越少。 原来初始化的代码放在 runTest中执行。修…

oracle pl/sql 包

包用于在逻辑上组合过程和函数&#xff0c;它由包规范和包体两部分组成。1)、我们可以使用create package命令来创建包&#xff0c;如&#xff1a;i、创建一个包sp_packageii、声明该包有一个过程update_saliii、声明该包有一个函数annual_income --声明该包有一个存储过程和一…

背单词软件 单词风暴 分享id_周一考研高效背单词系列(一):利用单词软件如何背好单词...

高效背单词考研单词作为考研路上的第一大难关&#xff0c;相信很多小伙伴都在这上面吃过不少苦&#xff0c;有同学更是看到密密麻麻的大纲词汇就头疼&#xff0c;但只要是学习就是有方法的&#xff0c;今天&#xff0c;我们开始推出高效背单词系列——墨墨背单词。另&#xff1…

linux c++ 编译 库,LINUX C/C++ 编译库关系

在LINUX 下安装个啥,都要涉及到编译,尤其是开源软件. 那么编译就涉及到C/C 和对应的库. 我们理一理之间的关系有助于MYSQL8源码编译libc glibc libc libstdc eglibc GCC G CMakeGDB从libc说起。libc是Linux下原来的标准C库&#xff0c;也就是当初写hello world时包含的头文件#…

Linux_学习_Day3_bash

Shell bash是外部程序&#xff1a;type/whichis bash。 shell&#xff0c; 子shell。可以利用bash打开另一个bash。即打开一个子shell。并且每个进程是独立存在的。对于子shell而言&#xff0c;bash并不认知其他bash的存在。 执行了多次bash&#xff0c;要退出只需exit。用pst…

mysql 之 优化 (收集于网络)

&#xff08;以下内容均来自于网络&#xff0c;如果有版权限制&#xff0c;请联系我0.0&#xff09; Mysql存储千亿级的数据&#xff0c;是一项非常大的挑战。Mysql单表可以存储10亿级的数据&#xff0c;只是这个时候性能非常差&#xff0c;项目中大量的实验证明&#xff0c;M…

easyui 收费_收费班长喻玉华三尺岗亭献青春

- 2020 第四期 人物访谈报道 -拼搏人生最美励志先锋人物专访2013年&#xff0c;22岁的她来到巴南高速这个大家庭中&#xff0c;成为恩阳收费站一名普通的收费员。怀着对事业的执着追求与热爱&#xff0c;经过两年不懈的努力&#xff0c;获得了领导和同事的认可和喜爱。2015年5月…