如何实现NSUserDefault以通过多个视图进行访问

时间:2011-12-14 00:34:57

标签: ios ipad nsuserdefaults multiple-views data-sharing

我正在尝试在多个视图中共享字符串和整数,以便在介绍性的iOS开发课程中进行最终项目,大约50,并且我想知道我将如何去做...我知道MVC范例是最好的但是我们没有得到非常先进的东西,特别是核心数据。我正在考虑使用NSUserDefaults,我知道这是错的,但这个应用程序不一定非常快,我认为这对我来说是最简单的方法。我的问题是,我将在何处以及如何声明我将使用的NSUserDefault对象?我们在课堂上唯一一次使用它是在一个视图中。如果我在加载的第一个视图中声明它我知道我可以使用其他视图访问它但是我是否需要将第一个视图的头文件导入其他视图中,或者它是否可以访问?


更新


所以我想我会尝试通过在NSUserDefaults中使ViewControllers属性变得更容易。然后,为了尝试获取值,我将每个ViewControllers的头文件实现到需要访问存储在NSUserDefaults(也具有NSUserDefault属性)中的数据的视图中。该应用程序运行非常严重,直到我进入该屏幕并且没有更新任何内容。我确定我的错误在于我如何实现NSUserDefaults,但我不确定如何正确地执行它。当我们在课堂上浏览它们时(实际上它是一个定向研究,“Sam在24小时内自学iPhone应用程序开发”(呕吐,这让我感到愤怒)),我们唯一一次使用它们是在单个视图应用程序中改变了白色背景的阿尔法,所以它可以用作闪光灯。这就是它的呈现方式:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setInteger: var forKey: kVar];
[userDefaults synchronize];

这就是我在我的应用中尝试的内容:

在我的ViewController.h个EACH视图文件中:

...

@interface AppetizerViewController : UIViewController{
    NSUserDefaults *userDefaults;

    ...
}

@property(assign)NSUserDefaults *userDefaults;

然后,当我点击一个按钮时,我想将该值保存到userDefaults

-(IBAction)plusEgg:(id)sender{
    eggs++;
    eggString = [NSString stringWithFormat:@"%d",eggs];
    eggQty.text = eggString;
    eggOrderedQty.text = eggString;

    [userDefaults setInteger:eggs forKey:kEggQty];
    [userDefaults synchronize];
    [self updateAppSubtotal];
}

-(IBAction)minusEgg:(id)sender{
    eggs--;

    if(eggs < 0){
        eggs = 0;
    }

    eggString = [NSString stringWithFormat:@"%d",eggs];
    eggQty.text = eggString;
    eggOrderedQty.text = eggString;

    [userDefaults setInteger:eggs forKey:kEggQty];
    [userDefaults synchronize];
    [self updateAppSubtotal];
} 

然后,由于我在所有视图的头文件中都有NSUserDefault Keys的所有常量,因此我将所有头文件实现为BillViewController,并尝试访问它们这样:

-(void)populateLabels{
    pieFinalQty.text = [NSString stringWithFormat:@"%d",
        [userDefaults integerForKey:kPieQty]];
    hazFinalQty.text = [NSString stringWithFormat:@"%d",
        [userDefaults integerForKey:kHazQty]];
    briFinalQty.text = [NSString stringWithFormat:@"%d",
        [userDefaults integerForKey:kBriQty]];
choFinalQty.text = [NSString stringWithFormat:@"%d",
        [userDefaults integerForKey:kChoQty]];
iceFinalQty.text = [NSString stringWithFormat:@"%d",
        [userDefaults integerForKey:kIceQty]];
}


-(void)getSubtotal{
    NSString *preSubString;
    NSString *subString;

    subFloat = [userDefaults floatForKey:kAppSub]+[userDefaults floatForKey:kBevSub]+
        [userDefaults floatForKey:kDesSub]+
        [userDefaults floatForKey:kEntSub]+[userDefaults floatForKey:kSidSub];

    if(subFloat < 10){
        preSubString = [[NSString alloc]initWithFormat:@"%1.2f",subFloat];
    }else if(subFloat < 100 && subFloat >= 10){
        preSubString = [[NSString alloc]initWithFormat:@"%2.2f",subFloat];
    }else if(subFloat < 1000 && subFloat >= 100){
        preSubString = [[NSString alloc]initWithFormat:@"%3.2f",subFloat];
    }else{
        preSubString = [[NSString alloc]initWithFormat:@"%4.2f",subFloat];
    }
    subString = [[NSString alloc]initWithFormat:@"$%@",preSubString];
    billSubtotal.text = subString;

    [preSubString release];
    [subString release];
} 

我很抱歉,你们试图向我解释的事情显然已经完全超出了我的头脑,并且我的命名惯例有点不同,但是我已经连续工作了大约15个小时。在明尼苏达州凌晨4点左右休息。我怎么能这样做?我也很抱歉,它可能需要明确如何实现它。

3 个答案:

答案 0 :(得分:7)

关于NSUserDefaults的好处是你不需要在任何地方实例化它:它已经可以从应用程序的任何地方访问。只需调用[NSUserDefaults standardUserDefaults],然后读取或写入该对象。在对象上调用synchronize以确保更改存储在磁盘上,然后在下一个位置检索standardUserDefaults对象,它将获得更新的信息。

编辑:根据您的上述代码,您可以进行以下更改以使用标准用户默认对象:

  1. 摆脱您的@property (assign) NSUserDefaults userDefaults;和您的成员变量NSUserDefaults userDefaults;
  2. 您想要读取或写入用户默认值的任何地方,创建一个临时变量: NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  3. 你能做到的另一种方式,就是你想要做的,就是将@property设置为标准的用户默认对象,这样就不必通过调用standardUserDefaults(因为看起来你使用它很多,这可能就是你应该去的方式)。

    这样做:

    1. 保留@property,但请将其设为(retain)而不是(assign)standardUserDefaults对象为autorelease d,因此您需要保留它自己)。 (可选)您可以移除NSUserDefaults userDefaults;行,因为@property无论如何为您创建
    2. 初始化视图控制器时(或在viewDidLoad中,就像我在这里做的那样),将userDefaults变量设置为标准用户默认对象:

      - (void)viewDidLoad
      {
          [super viewDidLoad];
          self.userDefaults = [NSUserDefaults standardUserDefaults];
      }
      
    3. 在与初始化方法对应的方法中发布用户默认值变量(dealloc方法为initviewDidUnloadviewDidLoad

      - (void)viewDidUnload
      {
          self.userDefaults = nil;
      }
      

答案 1 :(得分:2)

没有什么可以“宣布”。每当您说[NSUserDefaults standardUserDefaults]您正在访问用户默认值时,无论您说出来自哪里。如果您需要设置默认默认值(即某些键的初始值),请在程序中尽早完成,例如:在应用代表的applicationDidFinishLaunching中,通过调用registerDefaults

答案 2 :(得分:2)

如果您经常使用NSUserDefaults,那么创建自己的类别可能会很方便,以确保您的密钥中没有拼写错误。例如,说我经常得到并设置值,让编译器做一些检查以确保我没有输入错误的密钥会很方便,当然我们都喜欢自动完成。

// NSUserDefaults+PSProperties.h

@interface NSUserDefaults (PSProperties)

@property (nonatomic, assign) NSInteger ps_myInteger;

@end

// NSUserDefaults+PSProperties.m

NSString * const PSKeyMyInteger = @"PSKeyMyInteger";

@implementation NSUserDefaults (PSProperties)

- (NSInteger)ps_myInteger;
{
    return [self integerForKey:PSKeyMyInteger];
}

- (void)setPs_myInteger:(NSInteger)ps_myInteger;
{
    [self setInteger:ps_myInteger forKey:PSKeyMyInteger];
}

@end

因此,在我使用用户默认值的其他类中,我可以执行以下操作:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

defaults.ps_myInteger = 5;
[defaults synchronize];

NSLog(@"%i", defaults.ps_myInteger);

> 2011-12-14 01:10:28.041 SampleUserDefaults[5356:f803] 5

现在所有密钥都被隐藏,我使用与我的应用相关的更好的API与NSUserDefaults进行互动。