亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

從零開始學ios開發(二十):ApplicationSettingsandUserDefaults(下)

2019-11-14 20:15:45
字體:
來源:轉載
供稿:網友

在上一篇的學習中,我們知道了如何為一個App添加它的Settings設置項,在Settings設置項中我們可以添加哪些類型的控件,這些控件都是通過一個plist來進行管理的,我們只需對plist進行修改添加,就可以映射到Settings中。但是在上一篇中,我們并沒有學習Settings和App的交互,在這一篇中我們將進行學習,如何在一個App中讀取Settings中的值,如何在App中修改Settings中的值,好了,下面開始我們這次的學習。

1)NSUserDefaults
NSUserDefaults是ios自帶的一個對象,它的主要作用對Settings中的變量(我們添加的控件)進行取值和賦值。在上一篇中,我們在創建plist的時候,每一個Item都有一個Key,NSUserDefaults就是根據這個Key來找到對象,然后取得值,或者賦值。這個其實就是一個key-value對,NSUserDefaults在用法上和NSDictionary是一樣的,因此它也有很多類似的對象例如:objectForKey,intForKey,floatForKey,boolForKey,這些都很簡單。另外NSUserDefaults是一個單例模式(Singleton),也就是說在整個app中只有一個NSUserDefaults對象存在,這樣可以避免在2個地方同時對一個Item進行操作的情況,在程序中,我們使用standardUserDefaults方法來取得NSUserDefaults對象:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

2)從Settings中讀取值
打開BIDMainViewController.h,添加如下代碼

復制代碼
#import "BIDFlipsideViewController.h"#define kUsernameKey        @"username"#define kPassWordKey        @"password"#define kPRotocolKey        @"protocol"#define kWarpDriveKey       @"warp"#define kWarpFactorKey      @"warpFactor"#define kFavoriteTeaKey     @"favoriteTea"#define kFavoriteCandyKey   @"favoriteCandy"#define kFavoriteGameKey    @"favoriteGame"#define kFavoriteExcuseKey  @"favoriteExcuse"#define kFavoriteSinKey     @"favoriteSin"@interface BIDMainViewController : UIViewController <BIDFlipsideViewControllerDelegate>@property (weak, nonatomic) IBOutlet UILabel *usernameLabel;@property (weak, nonatomic) IBOutlet UILabel *passwordLabel;@property (weak, nonatomic) IBOutlet UILabel *protocolLabel;@property (weak, nonatomic) IBOutlet UILabel *warpDriveLabel;@property (weak, nonatomic) IBOutlet UILabel *warpFactorLabel;@property (weak, nonatomic) IBOutlet UILabel *favoriteTeaLabel;@property (weak, nonatomic) IBOutlet UILabel *favoriteCandyLabel;@property (weak, nonatomic) IBOutlet UILabel *favoriteGameLabel;@property (weak, nonatomic) IBOutlet UILabel *favoriteExcuseLabel;@property (weak, nonatomic) IBOutlet UILabel *favoriteSinLabel;- (void)refreshFields;@end
復制代碼

上面的代碼定義了10個常量Key,用來在之后的代碼中根據Key獲取Settings中的值,接著聲明10個IBOutlet,且他們都是指向Label的,最后聲明了一個refreshField方法,用于從Settings中讀取值然后賦給Label。

保存上面的code,然后在Project navigator中選中MainStoryboard.storyboard,在Layout area中會顯示2個View,分別是Main View和FlipSide View,我們選中Main View,然后打開Attribute inspector,找到Backgrund,將其背景色變為白色

在Main View的右下角,有一個Info button(一個圓圈,中間有一個字母i),選中它,然后在Attribute inspector中將其Type改成“Info Dark”

這樣就能夠很容易的找到它所在的地方了

如果你覺得直接在Main View中選擇一個白色的Info button很困難,那么你可以打開Main View Controller Scene,在里面你可以方便的找到它

好,接下來我們就要往Main View中拖控件了,一共拖20個Label,其中十個Label為靜態的,僅僅顯示文字,另外十個需要與剛才定義的IBOutlet關聯起來,用于顯示Settings中的值。

根據下圖的樣子,將Label拖入到Main View中

排列什么的無所謂,自己喜歡就好,主要是右邊的10個Label,他們的寬度都是到最右邊出現輔助線的位置,以保證能夠最大限度容納字符。

好了,下面的工作就是關聯IBOutlet和view上面的Label了,一共要關聯10個Label,選中Main View Controller Scene中的Main View Control,control-drag到Label上(右邊的一排Label),在彈出的框中選中相對應的IBOutlet

好了,保存所有的修改,下面開始編碼。

打開BIDMainViewController.m,添加以下code

復制代碼
@implementation BIDMainViewController- (void)refreshFields {    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    self.usernameLabel.text = [defaults objectForKey:kUsernameKey];    self.passwordLabel.text = [defaults objectForKey:kPasswordKey];    self.protocolLabel.text = [defaults objectForKey:kProtocolKey];    self.warpDriveLabel.text = [defaults boolForKey:kWarpDriveKey] ? @"Enabled" : @"Disabled";    self.warpFactorLabel.text = [[defaults objectForKey:kWarpFactorKey] stringValue];    self.favoriteTeaLabel.text = [defaults objectForKey:kFavoriteTeaKey];    self.favoriteCandyLabel.text = [defaults objectForKey:kFavoriteCandyKey];    self.favoriteGameLabel.text = [defaults objectForKey:kFavoriteGameKey];    self.favoriteExcuseLabel.text = [defaults objectForKey:kFavoriteExcuseKey];    self.favoriteSinLabel.text = [defaults objectForKey:kFavoriteSinKey];}- (void)viewDidAppear:(BOOL)animated {    [super viewDidAppear:animated];    [self refreshFields];}
復制代碼

首先我們實現了refreshFields方法,里面首先聲明了NSUserDefaults,用于獲取Settings中的值,之后調用objextForKey,通過Key來獲取10個Label的值,有2個比較特殊,第一個是kWarpDriveKey,由于WarpDrive是一個Switch,它返回的是一樣bool型,因此通過三元運算符來判斷YES或NO,如果是YES,返回“Enabled”,如果是NO,則返回“Disabled”。另一個比較特殊的是WarpFactor,由于WarpFactor是一個slider,返回的是一個int型,所以通過stringValue將int型轉換為string輸出。

然后我們重載了viewDidAppear方法,在view出現時調用refreshFields方法。

接著在BIDMainViewController.m中找到flipsideViewControllerDidFinish方法,添加如下code

- (void)flipsideViewControllerDidFinish:(BIDFlipsideViewController *)controller{    [self refreshFields];    [self dismissViewControllerAnimated:YES completion:nil];}

在Main View的右下角有一個info button,點擊它會切換到flipsideView,當從flipsideView切換回來的時候,就會調用上面的這個方法,然后再次刷新Settings中的數據。

好了,編譯運行一下程序,程序啟動后,在Settings中為AppSettings中的每一項賦值,然后打開AppSettings程序,就可以看到一下類似的截圖了。

 

3)將值寫入Settings
剛才我們通過NSUserDefaults從Settings讀取了值,現在我們將學習如何在程序中設置值,然后再寫入到Settings中。

打開MainStoryboard.storyboard,在layout area中,將Flipside View Controller布局成如下樣子

將View的背景色改成Light Gray color,View的title改成“Warp Settings”,添加了2個Label,添加了一個Switch和Slider,其中,Slider的左右兩個圖片是在其Attributs inspector中設置的

然后將slider的最小值設為1,最大值設為10,當前值設為5,同樣也是在Attributes inspector中進行設置

根據View中的內容,我們可以看出是針對Settings中的switch(WarpDrive)和slider(Warp Factor),打開BIDFlipsideViewController.h,添加如下code

復制代碼
#import <UIKit/UIKit.h>@class BIDFlipsideViewController;@protocol BIDFlipsideViewControllerDelegate- (void)flipsideViewControllerDidFinish:(BIDFlipsideViewController *)controller;@end@interface BIDFlipsideViewController : UIViewController@property (weak, nonatomic) id <BIDFlipsideViewControllerDelegate> delegate;@property (weak, nonatomic) IBOutlet UISwitch *engineSwitch;@property (weak, nonatomic) IBOutlet UISlider *warpFactorSlider;- (void)refreshFields;- (IBAction)engineSwitchTapped;- (IBAction)warpSliderTouched;- (IBAction)done:(id)sender;@end
復制代碼

兩個IBOutlet自然是指向View上的Switch和Slider的,refreshFields是用來刷新Flipside上的數據的,2個IBAction,當swtich發生改變時,觸發engineSwitchTapped事件,當slider發生改變時,觸發warpSliderTouched事件。

下面就是綁定了,展開Flipside View Controller Scene

然后選中Flipside View Controller根節點,control-drag到switch上,在彈出的框中選擇engineSwitch
同樣的方法,control-drag到slider上,選中warpFactorSlider

然后綁定事件,這次在Flipside View Controller選中switch,然后control-drag到Flipside View Controller Scene中的根節點Flipside View Controller上,會彈出一個框

選中enginSwitchTapped,同學選擇slider,control-drag,選擇warpSliderTouched

好了,界面上的操作全部完成了,下面開始編碼,打開BIDFlipsideViewController.m,添加如下代碼

復制代碼
- (void)viewDidLoad{    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.    [self refreshFields];}......- (void)refreshFields{    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    self.engineSwitch.on = [defaults boolForKey:kWarpDriveKey];    self.warpFactorSlider.value = [defaults floatForKey:kWarpFactorKey];}- (IBAction)engineSwitchTapped{    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    [defaults setBool:self.engineSwitch.on forKey:kWarpDriveKey];}- (IBAction)warpSliderTouched{    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    [defaults setFloat:self.warpFactorSlider.value forKey:kWarpFactorKey];}
復制代碼

首先在viewDidLoad中調用refreshFields的方法,接著實現了refreshFields,用于讀取Settings中的值并顯示在界面上,然后實現了2個IBAction,第一個用于保存Swtich的值,另一個保存Slider的值,2個方法都很簡單,看代碼就能看懂了。

好,保存編譯運行程序,在主界面中點擊右下角的info button,切換到flip view

flip view上顯示了Settings中Warp Drive的值和Warp Factor的值,然后我們調整一下,將Warp Engines設為ON,然后改變一下Warp Factor的位置,例如

然后按左上角的Done,返回main view,可以看到Warp Drive和Warp Factor的值也相應發生了改變

3)設置默認值
好了,到目前位置,我們已經可以做很多事情了,在App中讀取Settings中的值,在App中改變Settings中的值并保存回Settings中,但是大家有沒有發現,當你們第一運行app時,main view中其實是空的,什么都沒有,只有當我們退出程序,在Settings中設置好值以后,再回到App中,此時main view中的值才會有。其實這個情況是正確的,但是我們更希望能夠有一個默認值存在,我們無法在Settings.bundle中設置默認值,但是NSUserDefaults為我們提供了方法,打開BIDAppDelegate.m,添加如下代碼

復制代碼
#import "BIDAppDelegate.h"#import "BIDMainViewController.h"@implementation BIDAppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    // Override point for customization after application launch.    NSDictionary *defaults = @{kWarpDriveKey: @YES,                               kWarpFactorKey: @5,                               kFavoriteSinKey: @"Greed"};        [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];    return YES;}
復制代碼

從代碼中可以看到,NSUserDefaults通過registerDefaults方法設置默認值,它的參數是一個NSDictionary,在NSDictionary設置了3個對象的默認值。好了,在重新編譯運行程序之前,請確保將模擬器中的AppSettings刪除,再編譯運行,效果如下

可以看到,Warp Drive, Warp Factor, Favorite Sin三個對象都有默認值,和我們的預期是一樣的。

4)數據的同步
相信大家現在的手機至少是ios4以上的版本了,從ios4開始,ios就支持多任務了(雖然表面上是支持的),用戶可以在多個app之間進行切換。我們這個app當然也可以,但是有一個問題,我們運行程序,app默認界面如下

接著按Home鍵,回到桌面進入Settings,為Username

然后退出Settings,再進入AppSettings,你會發現剛才輸入的username并沒有顯示出來

ok,好,我們現在就來解決這個問題。首先簡單的說一下原理,這里用到了ios的一個機制:Notification。當一個后臺的程序被激活后,它將收到一個notification:UIApplicationWillEnterForegroundNotification,表示app即將顯示到前臺來。我們首先定義一個方法,當發生notification時會調用該方法,分別打開BIDMainViewController.m和BIDFlipsideViewController.m,分別添加如下代碼

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

NSUserDefaults的synchronize方法是用來同步Settings中的值的,當值同步完后,調用refreshFields方法,顯示到view中。

再分別為BIDMainViewController.m和BIDFlipsideViewController.m添加如下方法

復制代碼
- (void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated];        UIApplication *app = [UIApplication sharedApplication];    [[NSNotificationCenter defaultCenter] addObserver:self                                             selector:@selector(applicationWillEnterForeground:)                                                 name:UIApplicationWillEnterForegroundNotification                                               object:app];}
復制代碼

該方法用于監聽ios發出的notification,當監聽到UIApplicationWillEnterForegroundNotification通知后,就調用applicationWillEnterForeground方法。

我們還要更新2個已經寫好的方法,engineSwitchTapped和warpSliderTouched(在BIDFlipsideViewController.m中),修改如下

復制代碼
- (IBAction)engineSwitchTapped{    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    [defaults setBool:self.engineSwitch.on forKey:kWarpDriveKey];    [defaults synchronize];}- (IBAction)warpSliderTouched{    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    [defaults setFloat:self.warpFactorSlider.value forKey:kWarpFactorKey];    [defaults synchronize];}
復制代碼

新增了同步,每當值發生改變,就同步一下。

我們最后還要添加一個方法,用于釋放notification,還是分別為BIDMainViewController.m和BIDFlipsideViewController.m添加如下方法

- (void)viewDidDisappear:(BOOL)animated{    [super viewDidDisappear:animated];    [[NSNotificationCenter defaultCenter] removeObserver:self];}

當view消失后(進入后臺或者程序退出),將notification釋放。

好了,再次編譯運行app,按Home鍵回到桌面,進入Settings修改值再回到AppSettings,會發現相對于的值發生了改變。

5)總結
應該說,這篇以及上一篇關于Settings的內容都已經講完了,涵蓋了絕大部分關于Settings的操作,這部分的內容在程序設計開發的過程中還是相對有用的,對我來說收獲很大。下一篇開始,我們將重點講解ios對于數據的保存功能是如何實現的,又是一個很有用的內容,每個app幾乎都會使用到,有些保存的方法其實我們已經學習過了,在下一章會重點再介紹一次,希望下一篇會很快到來,我會努力的!


AppSettings_all.zip


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产999精品久久久影片官网| 亚洲性日韩精品一区二区| 国产成人精品在线| 黑人巨大精品欧美一区二区免费| 亚洲欧美色图片| 国产精品丝袜白浆摸在线| 欧洲亚洲免费视频| 欧美午夜性色大片在线观看| 粉嫩av一区二区三区免费野| 日本精品一区二区三区在线| 精品亚洲国产成av人片传媒| 九九热精品视频| 国产99久久精品一区二区| 国产精品一区二区三区久久久| 欧美视频专区一二在线观看| 精品久久久香蕉免费精品视频| 91在线免费看网站| 久久全球大尺度高清视频| 亚洲色图15p| 亚洲国产精品网站| 久久成年人免费电影| 国产成人精品优优av| 欧美日韩国产中文精品字幕自在自线| 91成人天堂久久成人| 亚洲午夜精品视频| 91亚洲一区精品| 午夜精品一区二区三区在线视| 亚洲成人久久一区| 欧美性感美女h网站在线观看免费| 伊人一区二区三区久久精品| 亚洲欧美日韩在线一区| 久久99国产精品久久久久久久久| 亚洲一区二区久久久| 18久久久久久| 91精品视频免费| 国产精品自拍视频| 欧美性受xxxx黑人猛交| 国产精品扒开腿做爽爽爽男男| 日韩在线中文字| 欧美精品18videosex性欧美| 欧美一级在线亚洲天堂| 在线视频欧美日韩精品| 日韩av一区二区在线观看| 久久噜噜噜精品国产亚洲综合| 久久成人精品视频| 亚洲欧美精品中文字幕在线| 成人黄色午夜影院| 日韩高清电影免费观看完整| 91久热免费在线视频| 国产99久久精品一区二区 夜夜躁日日躁| 国产精品第一视频| 一色桃子一区二区| 韩日精品中文字幕| 久久久噜噜噜久噜久久| 91在线观看免费网站| 国产精品免费久久久久久| 成人午夜在线观看| 91精品国产乱码久久久久久蜜臀| 国产成人小视频在线观看| 亚洲女人天堂av| 亚洲精品国产综合久久| 精品一区精品二区| 91视频8mav| 日韩亚洲精品电影| 精品视频在线播放免| 成人在线视频网站| 亚洲男人天堂古典| 欧美精品免费看| 久久五月天色综合| 国产精品热视频| 亚洲国产精品成人一区二区| 色妞在线综合亚洲欧美| 日本久久久久久久| 欧美成人剧情片在线观看| 精品国产乱码久久久久久婷婷| 成人h猎奇视频网站| 91国产视频在线播放| 国产日韩欧美在线视频观看| 久久国产精品亚洲| xxxx性欧美| 亚洲精品电影网在线观看| 久久九九国产精品怡红院| 日韩亚洲精品视频| 日韩最新中文字幕电影免费看| 国产精品h片在线播放| 久热精品视频在线观看| 欧美激情亚洲国产| 欧美亚洲成人精品| 国产精品一区二区三区久久久| 92国产精品久久久久首页| 亚洲激情电影中文字幕| 日韩中文字幕在线看| 国产精品吴梦梦| 77777亚洲午夜久久多人| 热99久久精品| 国产精品久久一区主播| 热门国产精品亚洲第一区在线| 亚洲国产精品va在线| 91精品久久久久久久久久另类| www.日韩免费| 色爱精品视频一区| 欧洲亚洲免费在线| 国产婷婷成人久久av免费高清| 欧美性jizz18性欧美| 91在线直播亚洲| 亚洲自拍偷拍色片视频| 日韩电视剧免费观看网站| 亚洲精品ady| 国产午夜精品视频免费不卡69堂| 亚洲影院色无极综合| 成人在线视频网站| 欧美夜福利tv在线| 久久久久国产精品www| 日本sm极度另类视频| 国产一区二区三区在线看| 欧美裸体男粗大视频在线观看| 国产大片精品免费永久看nba| 日韩成人在线播放| 97国产在线观看| 中文字幕精品国产| 国产一区二区三区日韩欧美| 国产精品久久久久久久av大片| 92看片淫黄大片看国产片| 成人夜晚看av| 欧美日韩国内自拍| 欧美激情久久久久久| 欧美日韩亚洲天堂| 日韩资源在线观看| 亚洲国产精品久久91精品| 亚洲国产精品久久久久久| 正在播放亚洲1区| 亚洲综合精品伊人久久| 欧美www视频在线观看| 国产精品日日做人人爱| 亚洲天堂网站在线观看视频| 国产日韩欧美另类| 亚洲天堂第一页| 亚洲在线www| 色一情一乱一区二区| 亚洲欧美日韩国产精品| 一区国产精品视频| 日韩在线中文视频| 中文字幕亚洲二区| 久久久www成人免费精品| 中文字幕在线看视频国产欧美| 国产精品国产三级国产aⅴ9色| 精品无人区乱码1区2区3区在线| 欧美一级片久久久久久久| 亚洲国产又黄又爽女人高潮的| 秋霞成人午夜鲁丝一区二区三区| 亚洲天堂一区二区三区| 成人欧美一区二区三区在线湿哒哒| 这里只有精品视频| 亚洲免费影视第一页| 成人免费高清完整版在线观看| 色哟哟入口国产精品| 国产成人91久久精品| 亚洲女性裸体视频| 欧洲成人午夜免费大片| 成人精品视频久久久久| 欧美激情图片区| 国产精品福利在线观看网址| 亚洲一区二区三区视频| 国产在线视频不卡|