• iOS开发应用设置及用户默认设置【2、读取应用中的设置】


            在上一节中,我们通过探讨应用的系统设置的基本功能,了解运用bundle捆绑包以及plist文件的基本开发。用户能够使用设置应用来声明他们的偏好设置,那么我们怎样去调用用户所设置的参数呢,上节我们只创建了Setting.bundle捆绑包,在这个基础上,这一节,我们将继续讨论,关于如何读取应用中的设置,以及让app应用与设置的数据同步。

    我们将通过本节内容达到的效果如下:

        

    【图1 app应用界面】

    【本次开发环境: Xcode:7.2     iOS Simulator:iphone6S plus   By:啊左】    

    一、获取用户设置

    1、NSUserDefaults类的介绍

    访问用户的设置需要调用NSUserDefaults类,NSUserDefaults为单例类,需要调用类方法standardUserDefaults来获取指向标准用户默认设置的指针:

    NSUserDefaults *defaults =  [NSUserDefaults standardUserDefaults];
    defaults可以像NSDictionary类一样进方法的调用,例如“objectForKey:”,会返回一个Object-C对象,如NSString、NSDate、NSNumber。若需要获取整型、浮点型等方式,可以用“intForKey:”、“floatForKey”、“boolForKey”等其他方法。

    2、键值

    在上一节中,plist属性列表中的偏好设置字段,每个条目都有特定的键,例如Item1对应的是“officer”、滑块Item6对应的是“SliderValue”,这些键都是做为调用该项的ID。

    因此我们可以先把这些键放在自己创建的头文件"settingHead.h"中,便于调用。内容如下:

    #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、关联相关控件

    接下来,我们使用Main.storyboard创建14个label、一个开关、一个滑块,为左边8个label修改为Officer、code等内容如下:


    【图2  Main.storyboard设置界面】

    确认该视图关联的是ViewController,然后打开辅助编辑器(或者在Main.storyboard界面按下option+command+return),按住control键分别从Main.storyboard图标拖动到ViewController.h中,为右边6个label以及滑块、开关添加在ViewController.h的接口,代码如下:

    #import <UIKit/UIKit.h>
    
    @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;
    
    //滑块、开关接口
    @property (weak, nonatomic) IBOutlet UISwitch *enginesSwitch;
    @property (weak, nonatomic) IBOutlet UISlider *WarpSlider;
    
    //滑块、开关的接口方法(修改用户默认设置)
    - (IBAction)enginesSwitchBtn:(UISwitch *)sender;
    - (IBAction)WarpSliderBtn:(UISlider *)sender;
    
    @end
    

    在ViewController.m中,敲入: #import "settingHead.h"   添加键集合的头文件,然后添加一个更新app界面数据的方法:  -(void)refreshValue ,代码如下:

     1 #import "ViewController.h"
     2 #import "settingHead.h"
     3 
     4 @implementation ViewController
     5 
     6 - (void)viewDidLoad {
     7     [super viewDidLoad];
     8     self.view.backgroundColor = [UIColor orangeColor];
     9     [self refreshValue];
    10 }
    11 
    12 -(void)refreshValue
    13 {
    14     NSUserDefaults *defaults =  [NSUserDefaults standardUserDefaults];
    15     self.label1.text = [defaults objectForKey:Officer];
    16     self.label2.text = [defaults objectForKey:AuthorizationCode];
    17     self.label3.text = [defaults objectForKey:Rank];
    18     self.label4.text = [defaults boolForKey:IsWarp]?@"Enable":@"Disable";
    19     self.label5.text = [[defaults objectForKey:SliderValue] stringValue];
    20     
    21     self.enginesSwitch.on = [defaults boolForKey:IsWarp];
    22     self.WarpSlider.value = [defaults floatForKey:SliderValue];
    23 }

    在以上的refreshValue方法,首先通过调用NSUserDefaults类获取了标准用户默认设置,然后调用objectForKey方法访问获取对应键值的内容、

    需要注意的是label1到label5,除了label4外,都是以NSString对象的形式返回,label4中defaults调用键值为IsWarp的方法返回的是bool值。因此我们得到结果后给予判断再赋值给label4的文本;

    而label5由于是内容为滑块的值,是以NSNumber形式返回的,因此需要调用改对象的stringValue方法来获取它存储的值的字符串表示。

    二、在应用中修改用户默认设置

    应用中修改用户默认设置所调用的方法为:“setObject forKey”,在在ViewController.m中,需要在关联的开关滑块方法WarpSliderBtn、enginesSwitchBtn中添加如下代码:

     1 - (IBAction)WarpSliderBtn:(UISlider *)sender {
     2     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     3     [defaults setFloat:self.WarpSlider.value forKey:SliderValue];
     4     [defaults synchronize];
     5 }
     6 - (IBAction)enginesSwitchBtn:(UISwitch *)sender {
     7     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     8     [defaults setBool:self.enginesSwitch.on forKey:IsWarp];
     9     [defaults synchronize];
    10 }

    运行、我们可以看到如下界面:

    【图3  】

    我们可以看到,即使我们为Multi Value、IsWarp设置默认值得,依然不会显示在我们的应用中,这是因为:我们的应用完全不知道设置捆绑包中已保存的该应用的偏好设置,即使我们在设置中设置好相应的值,然后再运行一次可以看到应用上显示值,但是当我们删除掉运用再运行一次,还是显示为空值,而不能看到默认值。

    我们可以作如下处理:如果我们尝试查找未设置的键/值,但该键至少会有一个默认值,可以用registerDefaults:方法,为了使得改设置在整个运用中都能有效,最好在应用启动时就调用它

    因此,点击AppDelegate.m文件,添加"settingHead.h”头文件,然后在didFinishLaunchingWithOptions中键入以下代码:

    1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    2     // Override point for customization after application launch.
    3     
    4     NSDictionary *dict = @{@"warp":@YES,
    5                            @"warpFactor":@5,
    6                            };
    7     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
    8     return YES;
    9 }

    按下command+shift+H ,在ios模拟器主页上面长按我们创建的app,删除它,然后按下command+R再运行一次我们可以看到刚刚我们通过registerDefaults:方法设置的默认值。

    三、同步系统设置与应用上的数据

    现在我们可以尝试下通过调整应用来修改系统设置的值,但是奇怪的是:当我们修改系统设置,再打开app应用上面的数据也没有变化,当我们修改app上面的滑块与开关,再查看系统设置也是没有变化。

       这也是iOS系统的一个特点:当应用在运行时返回主屏幕,并不会退出应用,而是由操作系统在后台将其暂停了,这样它就可以随时能够快速启动,因为用户在切换应用时,重新唤醒一个应用比重新启动一个应用要省下很多时间,这使得iOS系统下应用的切换更加高效快捷。这也是后台应用的基本知识。

    那么在这个例子中,我们应该如何同步更新数据呢,其实只要在唤醒的时候添加一个功能:重新加载同步用户偏好设置并重新显示它们的内容。

    接下来我们需要运用到“通知”这一个对象之间进行通信的轻量级机制。通知中心是一个单例对象,作用是在对象之间传送通知。“通知”通常是在某些事件发生时发送的说明,UIApplicaton类会发送大量的通知(可以从Xcode的文档阅读器中找到这些更加详细的内容,在UIApplicaton页面的底部)。

    应用在回到前台时,刷新一下它显示的内容,因此我们需要调用名为 “UIApplicationWillEnterForegroundNotification”的通知,编写viewWillAppear:方法时,我们会订阅该通知,并告诉通知中心该通知出现时需要调用的方法,这个方法我们可以命名为:“applicationwillenterforegound”、

    点击ViewController.m,添加以下代码:

    1 -(void)applicationwillenterforegound:(NSNotification *)notification
    2 {
    3     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    4     //进行应用设置与控件上的数据同步
    5     [defaults synchronize];
    6     [self refreshValue];
    7 }

    其中,我们可以看到defaults调用synchronize方法,该方法强制用户默认值保存尚未保存的修改,然后从存储中重新加载所有未修改的偏好设置。事实上,这是在强制它重新读取已保存的偏好设置,从而获取设置应用中所作的修改,然后调用refreshValue:方法来个更新显示的内容。

    Now,我们需要在ViewController.m中实现viewWillAppear:方法,使得该控制器订阅我们关注的“UIApplicationWillEnterForegroundNotification”通知。如下:

    1 -(void)viewWillAppear:(BOOL)animated
    2 {
    3     [super viewWillAppear:animated];
    4     //注册观测者
    5     UIApplication *app = [UIApplication sharedApplication];
    6     [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(applicationwillenterforegound:) name:UIApplicationWillEnterForegroundNotification object:app];
    7 }

    在该addObserver:  selectornameobject: 方法中,

    observer传递的是self,也就是我们的控制器本身;

    selector,调用的是我们自己写的选择器方法,用于告诉通知中心在该通知发出时调用该方法;

    name是我们要接収的通知的名称,一般可以在Xcode的文档阅读器中找到这些更加详细的内容;

    最后一个参数app,是我们关心的获得通知的来源对象,如果改为nil,表示只要有方法发出“UIApplicationWillEnterForegroundNotification”通知,我们就会得到通知。

    这样,我们就完成了,回到app前台重新加载内容的开发。

     

    那么当用户在应用中操作控件,又怎样把内容同步到系统的默认设置里面呢?很简单,只要在我们设置的控件,开关与滑块的方法中添加一行 “[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];
    }

     

    【注意:调用synchronize:方法的开销会很大,因为要比较应用以及系统设置中的所有用户偏好设置,因此应该尽量减少对synchronize的调用,不过像我们此次的项目中,在响应每个用户操作时调用它一次,并不会造成任何显著的性能问题。 

    当然,为了使得系统的工作过程更加清晰,我们可以在通知系统不需要接收到通知时,在viewDidDisappear中撤销注册,因此我们可以添加代码如下:

    -(void)viewDidDisappear:(BOOL)animated
     {
          [super viewDidDisappear:animated];
          /*
            注销监听  也可以用removeObserver:self name: object:方法来撤销对特定通知的订阅,但以下这种更加方便:直接告知确保通知中心彻底忘记我们的observer的方法,不管注册它是为了        接收多少种通知。
          */
          [[NSNotificationCenter defaultCenter] removeObserver:self];
     }

     按下“command+R”运行。在应用的空间【参照图1】以及系统设置上面编辑,以及切换时查看同步效果。

     

    做完以上工作,我们已经可以了解了设置应用和用户默认机制的基本概念,懂得如何添加捆绑包、为应用的偏好设置构建结构化的视图、通过NSUserDedeults读写偏好设置以及修改设置等内容,并且开发了相关的项目。相信在iOS开发的工作学习你一定也会用到相关的技术,并不断完善。

     by:啊左~ (转载请标明原文出处,谢谢支持 ~ ^-^ ~)
  • 相关阅读:
    Unique Binary Search Trees——LeetCode
    Binary Tree Inorder Traversal ——LeetCode
    Maximum Product Subarray——LeetCode
    Remove Linked List Elements——LeetCode
    Maximum Subarray——LeetCode
    Validate Binary Search Tree——LeetCode
    Swap Nodes in Pairs——LeetCode
    Find Minimum in Rotated Sorted Array——LeetCode
    Linked List Cycle——LeetCode
    VR AR MR
  • 原文地址:https://www.cnblogs.com/azuo/p/5098544.html
Copyright © 2020-2023  润新知