iOS開發(fā)--應(yīng)用設(shè)置及用戶默認(rèn)設(shè)置【2、讀取應(yīng)用中的設(shè)置】

在上一節(jié)中,我們通過探討應(yīng)用的系統(tǒng)設(shè)置的基本功能,了解運用bundle捆綁包以及plist文件的基本開發(fā)。用戶能夠使用設(shè)置應(yīng)用來聲明他們的偏好設(shè)置,那么我們怎樣去調(diào)用用戶所設(shè)置的參數(shù)呢,上節(jié)我們只創(chuàng)建了Setting.bundle捆綁包,在這個基礎(chǔ)上,這一節(jié),我們將繼續(xù)討論,關(guān)于如何讀取應(yīng)用中的設(shè)置,以及讓app應(yīng)用與設(shè)置的數(shù)據(jù)同步。

我們將通過本節(jié)內(nèi)容達到的效果如下:

【圖1 app應(yīng)用界面】


【本次開發(fā)環(huán)境: Xcode:7.2 ? ??iOS Simulator:iphone6S plus ? By:啊左】

一、獲取用戶設(shè)置

1、NSUserDefaults類的介紹

訪問用戶的設(shè)置需要調(diào)用NSUserDefaults類,NSUserDefaults為單例類,需要調(diào)用類方法standardUserDefaults來獲取指向標(biāo)準(zhǔn)用戶默認(rèn)設(shè)置的指針:

NSUserDefaults *defaults =? [NSUserDefaults standardUserDefaults];

defaults可以像NSDictionary類一樣進方法的調(diào)用,例如“objectForKey:”,會返回一個Object-C對象,如NSString、NSDate、NSNumber。若需要獲取整型、浮點型等方式,可以用“intForKey:”、“floatForKey”、“boolForKey”等其他方法。

2、鍵值

在上一節(jié)中,plist屬性列表中的偏好設(shè)置字段,每個條目都有特定的鍵,例如Item1對應(yīng)的是“officer”、滑塊Item6對應(yīng)的是“SliderValue”,這些鍵都是做為調(diào)用該項的ID。

因此我們可以先把這些鍵放在自己創(chuàng)建的頭文件"settingHead.h"中,便于調(diào)用。內(nèi)容如下:

#ifndef settingHead_h

#define settingHead_h

#define Officer? ? ? ? ? ? @"officer"

#define AuthorizationCode? @"authorizationCode"

#define Rank? ? ? ? ? ? ? @"rank"

#define IsWarp? ? ? ? ? ? @"IsWarp"

#define SliderValue? ? ? ? @"SliderValue"

#define moreFactor? ? ? ? @"MoresliderValue"

#endif /* settingHead_h */

3、關(guān)聯(lián)相關(guān)控件

接下來,我們使用Main.storyboard創(chuàng)建14個label、一個開關(guān)、一個滑塊,為左邊8個label修改為Officer、code等內(nèi)容如下:

【圖2? Main.storyboard設(shè)置界面】

確認(rèn)該視圖關(guān)聯(lián)的是ViewController,然后打開輔助編輯器(或者在Main.storyboard界面按下option+command+return),按住control鍵分別從Main.storyboard圖標(biāo)拖動到ViewController.h中,為右邊6個label以及滑塊、開關(guān)添加在ViewController.h的接口,代碼如下:

#import

@interface ViewController : UIViewController

//5個label接口

@property (weak, nonatomic) IBOutlet UILabel *label1;

@property (weak, nonatomic) IBOutlet UILabel *label2;

@property (weak, nonatomic) IBOutlet UILabel *label3;

@property (weak, nonatomic) IBOutlet UILabel *label4;

@property (weak, nonatomic) IBOutlet UILabel *label5;

//滑塊、開關(guān)接口

@property (weak, nonatomic) IBOutlet UISwitch *enginesSwitch;

@property (weak, nonatomic) IBOutlet UISlider *WarpSlider;

//滑塊、開關(guān)的接口方法(修改用戶默認(rèn)設(shè)置)

- (IBAction)enginesSwitchBtn:(UISwitch *)sender;

- (IBAction)WarpSliderBtn:(UISlider *)sender;

@end

在ViewController.m中,敲入:#import"settingHead.h" ? 添加鍵集合的頭文件,然后添加一個更新app界面數(shù)據(jù)的方法:-(void)refreshValue ,代碼如下:

#import "ViewController.h"

#import "settingHead.h"

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

self.view.backgroundColor = [UIColor orangeColor];

[self refreshValue];

}

-(void)refreshValue

{

NSUserDefaults *defaults =? [NSUserDefaults standardUserDefaults];

self.label1.text = [defaults objectForKey:Officer];

self.label2.text = [defaults objectForKey:AuthorizationCode];

self.label3.text = [defaults objectForKey:Rank];

self.label4.text = [defaults boolForKey:IsWarp]?@"Enable":@"Disable";

self.label5.text = [[defaults objectForKey:SliderValue] stringValue];

self.enginesSwitch.on = [defaults boolForKey:IsWarp];

self.WarpSlider.value = [defaults floatForKey:SliderValue];

}

在以上的refreshValue方法,首先通過調(diào)用NSUserDefaults類獲取了標(biāo)準(zhǔn)用戶默認(rèn)設(shè)置,然后調(diào)用objectForKey方法訪問獲取對應(yīng)鍵值的內(nèi)容、

需要注意的是label1到label5,除了label4外,都是以NSString對象的形式返回,label4中defaults調(diào)用鍵值為IsWarp的方法返回的是bool值。因此我們得到結(jié)果后給予判斷再賦值給label4的文本;

而label5由于是內(nèi)容為滑塊的值,是以NSNumber形式返回的,因此需要調(diào)用改對象的stringValue方法來獲取它存儲的值的字符串表示。

二、在應(yīng)用中修改用戶默認(rèn)設(shè)置

應(yīng)用中修改用戶默認(rèn)設(shè)置所調(diào)用的方法為:“setObjectforKey:”,在在ViewController.m中,需要在關(guān)聯(lián)的開關(guān)滑塊方法WarpSliderBtn、enginesSwitchBtn中添加如下代碼:

- (IBAction)WarpSliderBtn:(UISlider *)sender {

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setFloat:self.WarpSlider.value forKey:SliderValue];

[defaults synchronize];

}

- (IBAction)enginesSwitchBtn:(UISwitch *)sender {

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setBool:self.enginesSwitch.on forKey:IsWarp];

[defaults synchronize];

}

運行、我們可以看到如下界面:

【圖3】

我們可以看到,即使我們?yōu)镸ulti Value、IsWarp設(shè)置默認(rèn)值得,依然不會顯示在我們的應(yīng)用中,這是因為:我們的應(yīng)用完全不知道設(shè)置捆綁包中已保存的該應(yīng)用的偏好設(shè)置,即使我們在設(shè)置中設(shè)置好相應(yīng)的值,然后再運行一次可以看到應(yīng)用上顯示值,但是當(dāng)我們刪除掉運用再運行一次,還是顯示為空值,而不能看到默認(rèn)值。

我們可以作如下處理:如果我們嘗試查找未設(shè)置的鍵/值,但該鍵至少會有一個默認(rèn)值,可以用registerDefaults:方法,為了使得改設(shè)置在整個運用中都能有效,最好在應(yīng)用啟動時就調(diào)用它

因此,點擊AppDelegate.m文件,添加"settingHead.h”頭文件,然后在didFinishLaunchingWithOptions中鍵入以下代碼:

-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Override point for customization after application launch.

NSDictionary *dict = @{@"warp":@YES,

@"warpFactor":@5,

};

[[NSUserDefaults standardUserDefaults] registerDefaults:dict];

return YES;

}

按下command+shift+H ,在ios模擬器主頁上面長按我們創(chuàng)建的app,刪除它,然后按下command+R再運行一次我們可以看到剛剛我們通過registerDefaults:方法設(shè)置的默認(rèn)值。

三、同步系統(tǒng)設(shè)置與應(yīng)用上的數(shù)據(jù)

現(xiàn)在我們可以嘗試下通過調(diào)整應(yīng)用來修改系統(tǒng)設(shè)置的值,但是奇怪的是:當(dāng)我們修改系統(tǒng)設(shè)置,再打開app應(yīng)用上面的數(shù)據(jù)也沒有變化,當(dāng)我們修改app上面的滑塊與開關(guān),再查看系統(tǒng)設(shè)置也是沒有變化。

這也是ios系統(tǒng)的一個特點:當(dāng)應(yīng)用在運行時返回主屏幕,并不會退出應(yīng)用,而是由操作系統(tǒng)在后臺將其暫停了,這樣它就可以隨時能夠快速啟動,因為用戶在切換應(yīng)用時,重新喚醒一個應(yīng)用比從新啟動一個應(yīng)用要省下很多時間,這使得ios系統(tǒng)下應(yīng)用的切換更加高效快捷。這也是后臺應(yīng)用的基本知識。

那么在這個例子中,我們應(yīng)該如何同步更新數(shù)據(jù)呢,其實只要在喚醒的時候添加一個功能:重新加載同步用戶偏好設(shè)置并重新顯示它們的內(nèi)容。

接下來我們需要運用到“通知”這一個對象之間進行通信的輕量級機制。通知中心是一個單例對象,作用是在對象之間傳送通知。“通知”通常是在某些事件發(fā)生時發(fā)送的說明,UIApplicaton類會發(fā)送大量的通知(可以從Xcode的文檔閱讀器中找到這些更加詳細(xì)的內(nèi)容,在UIApplicaton頁面的底部)。

應(yīng)用在回到前臺時,刷新一下它顯示的內(nèi)容,因此我們需要調(diào)用名為 “UIApplicationWillEnterForegroundNotification”的通知,編寫viewWillAppear:方法時,我們會訂閱該通知,并告訴通知中心該通知出現(xiàn)時需要調(diào)用的方法,這個方法我們可以命名為:“applicationwillenterforegound”、

點擊ViewController.m,添加以下代碼:

-(void)applicationwillenterforegound:(NSNotification *)notification

{

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

//進行應(yīng)用設(shè)置與控件上的數(shù)據(jù)同步

[defaults synchronize];

[self refreshValue];

}

其中,我們可以看到defaults調(diào)用synchronize方法,該方法強制用戶默認(rèn)值保存尚未保存的修改,然后從存儲中重新加載所有未修改的偏好設(shè)置。事實上,這是在強制它重新讀取已保存的偏好設(shè)置,從而獲取設(shè)置應(yīng)用中所作的修改,然后調(diào)用refreshValue:方法來個更新顯示的內(nèi)容。

Now,我們需要在ViewController.m中實現(xiàn)viewWillAppear:方法,使得該控制器訂閱我們關(guān)注的“UIApplicationWillEnterForegroundNotification”通知。如下:

-(void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

//注冊觀測者

UIApplication *app = [UIApplication sharedApplication];

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(applicationwillenterforegound:) name:UIApplicationWillEnterForegroundNotification object:app];

}

在該addObserver:selector:name:object:方法中,

observer傳遞的是self,也就是我們的控制器本身;

selector,調(diào)用的是我們自己寫的選擇器方法,用于告訴通知中心在該通知發(fā)出時調(diào)用該方法;

name是我們要接収的通知的名稱,一般可以在Xcode的文檔閱讀器中找到這些更加詳細(xì)的內(nèi)容;

最后一個參數(shù)app,是我們關(guān)心的獲得通知的來源對象,如果改為nil,表示只要有方法發(fā)出“UIApplicationWillEnterForegroundNotification”通知,我們就會得到通知。

這樣,我們就完成了,回到app前臺重新加載內(nèi)容的開發(fā)。

那么當(dāng)用戶在應(yīng)用中操作控件,又怎樣把內(nèi)容同步到系統(tǒng)的默認(rèn)設(shè)置里面呢?很簡單,只要在我們設(shè)置的控件,開關(guān)與滑塊的方法中添加一行 “[defaults synchronize]” 即可。

- (IBAction)WarpSliderBtn:(UISlider *)sender {

NSUserDefaults*defaults =[NSUserDefaults standardUserDefaults];? ?

?[defaults setFloat:self.WarpSlider.value forKey:SliderValue];

[defaults synchronize];

}

- (IBAction)enginesSwitchBtn:(UISwitch *)sender {

NSUserDefaults*defaults =[NSUserDefaults standardUserDefaults];? ??

[defaults setBool:self.enginesSwitch.on forKey:IsWarp];

[defaults synchronize];

}

【注意:調(diào)用synchronize:方法的開銷會很大,因為要比較應(yīng)用以及系統(tǒng)設(shè)置中的所有用戶偏好設(shè)置,因此應(yīng)該盡量減少對synchronize的調(diào)用,不過像我們此次的項目中,在響應(yīng)每個用戶操作時調(diào)用它一次,并不會造成任何顯著的性能問題。

當(dāng)然,為了使得系統(tǒng)的工作過程更加清晰,我們可以在通知系統(tǒng)不需要接收到通知時,在viewDidDisappear中撤銷注冊,因此我們可以添加代碼如下:

-(void)viewDidDisappear:(BOOL)animated

{

[super viewDidDisappear:animated];

/*

注銷監(jiān)聽? 也可以用removeObserver:self name: object:方法來撤銷對特定通知的訂閱,但以下這種更加方便:直接告知確保通知中心徹底忘記我們的observer的方法,不管注冊它是為了接收多少種通知。

*/

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

按下“command+R”運行。在應(yīng)用的空間【參照圖1】以及系統(tǒng)設(shè)置上面編輯,以及切換時查看同步效果。

做完以上工作,我們已經(jīng)可以了解了設(shè)置應(yīng)用和用戶默認(rèn)機制的基本概念,懂得如何添加捆綁包、為應(yīng)用的偏好設(shè)置構(gòu)建結(jié)構(gòu)化的視圖、通過NSUserDedeults讀寫偏好設(shè)置以及修改設(shè)置等內(nèi)容,并且開發(fā)了相關(guān)的項目。相信在iOS開發(fā)的工作學(xué)習(xí)你一定也會用到相關(guān)的技術(shù),并不斷完善。



(轉(zhuǎn)載請標(biāo)明原文出處,謝謝支持 ~ ^-^ ~)

? by:啊左~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容