使用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.pswp.cn/news/454681.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454681.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454681.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Netty自娛自樂之協議棧設計

---恢復內容開始--- 俺工作已經一年又6個月了&#xff0c;想想過的真快&#xff0c;每天寫業務&#xff0c;寫業務&#xff0c;寫業務......。然后就是祈禱著&#xff0c;這次上線不要出現線上bug。繼續這每天無聊的增刪改查&#xff0c;學習學習一下自己感興趣的事&#xff0c…

Linux 狀態命令之磁盤狀態 df du

df df&#xff08;disk free&#xff09;命令用于顯示目前在 Linux 系統上的文件系統磁盤使用情況統計。獲取硬盤被占用了多少空間&#xff0c;目前還剩下多少空間等信息&#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;由父進程來建立。管道兩端的進程各自都將該管道視作一個文件。一個…

看穿面試這件事兒……

報 版權聲明&#xff1a;原創作品&#xff0c;允許轉載&#xff0c;轉載時請務必以超鏈接形式標明文章原始出版、作者信息和本聲明。否則將追究法律責任。本文地址&#xff1a; http://blog.csdn.net/jobchanceleo/archive/2007/04/17/1568254.aspx 有個朋友Min十幾年工作經驗&…

阿里云胡曉明:數據智能將為城市生活帶來真正價值

8月30日&#xff0c;在2017全球&#xff08;上海&#xff09;人工智能創新峰會-世界人工智能城市規劃大會上&#xff0c;阿里巴巴集團資深副總裁、阿里云總裁胡曉明作《通往智能之路》主題演講&#xff0c;指出數據智能將從交通、醫療、城市治理等方面影響城市生活&#xff0c;…

MySQL 之 information_schema

一、information_schema簡介 在MySQL中&#xff0c;把 information_schema 看作是一個數據庫&#xff0c;確切說是信息數據庫。其中保存著關于MySQL服務器所維護的所有其他數據庫的信息。如數據庫名&#xff0c;數據庫的表&#xff0c;表欄的數據類型與訪問權 限等。在INFORMA…

【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公司的筆試/面試題則蘊含著諸多思想與設計&…

python threading 結束線程

python threading 啟動的線程&#xff0c;并沒有提供終止線程的方法&#xff0c;現總結一下在網上找到的方法 1、通過threading.Thread._Thread__stop()結束線程 import time import threading def f():while 1:time.sleep(0.1)print(1)t threading.Thread(targetf) t.start…

快讀模板

快速讀入字符 inline char readc(){ static char buf[1 << 18], *fs, *ft;return (fs ft && (ft (fs buf) fread(buf, 1, 1 << 18, stdin)), fs ft) ? EOF : *fs; } 快速讀入數字 inline int readint(){register char creadc();register int res0;re…

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命令&#…

13,反轉鏈表《劍指offer》

題目&#xff1a; 輸入一個鏈表&#xff0c;反轉鏈表后&#xff0c;輸出鏈表的所有元素。 思路&#xff1a; 反轉鏈表&#xff0c;對于片段 1--->2--->3循環操作&#xff1b; 要反轉鏈表需要兩步&#xff1a; 一&#xff0c;將2->next指向1 &#xff08;如果不保存3那…

什么是面試的關鍵?資深HR告訴你!

求職指南、面試寶典、應聘手冊……到任何一個書店去轉轉&#xff0c;總能發現一兩本這樣的書&#xff0c;有關面試應聘的包裝技巧實在太多&#xff0c;既讓應聘者眼花繚亂、無所適從&#xff0c;也讓人事經理頭疼&#xff0c;總擔心會被應聘者的包裝所蒙騙。東方控股集團有限公…

windows商店_Windows記事本應用現在可以從Microsoft Store中獲得

早在2019年8月&#xff0c;微軟就宣布將把人們最常用的Windows記事本應用搬到應用商店&#xff0c;讓這款深受用戶喜愛的應用更新速度更快、響應更靈敏。12月晚些時候&#xff0c;微軟卻放棄了這一計劃&#xff0c;也沒有給出太多理由。但現在&#xff0c;這一計劃已經完成&…