2

我正在尝试在 50 岁左右的 iOS 开发入门课程中的最终项目的多个视图中共享字符串和整数,我想知道我将如何去做……我知道 MVC 范式是最好的,但我们没有没有得到非常先进的东西,尤其是核心数据。我正在考虑使用 NSUserDefaults,我知道这是错误的,但这个应用程序不必非常快,我认为这对我来说是最简单的方法。我的问题是,我将在哪里以及如何声明我将使用的 NSUserDefault 对象?我们在课堂上唯一一次使用它是在一个视图中。如果我在加载的第一个视图中声明它,我知道我可以使用其他视图访问它,但是我是否需要将第一个视图的头文件导入到其他每个视图中,或者无论如何都可以访问它?


更新


所以我想我会尝试通过NSUserDefaults在所有ViewControllers. 然后,为了尝试取回这些值,我将每个的标题实现ViewControllers到需要访问存储在 NSUserDefaults 中的数据(也有一个NSUserDefault属性)的视图中。该应用程序运行得非常好,直到我进入该屏幕并且没有任何更新。我确定我的错误在于我如何实施 NSUserDefaults但我不确定如何正确地做到这一点。当我们在课堂上复习它们时(实际上是“Sam's Teach Yourself iPhone Application Development in 24 Hrs”的定向研究(呕吐,这让我很生气)),我们唯一一次使用它们是在单一视图应用程序中改变了白色背景的 alpha,因此它可以用作闪光灯。它是这样呈现的:

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

这是我在我的应用程序中尝试的:

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

...

@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:00 左右。我该怎么办?我也很抱歉,它可能必须明确说明如何实现它。

4

3 回答 3

7

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

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

  1. 摆脱你@property (assign) NSUserDefaults userDefaults;和你的成员变量NSUserDefaults userDefaults;
  2. 在您想要读取或写入用户默认值的任何地方,创建一个临时变量: NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

你可以做的另一种方法,这似乎是你想要做的,将设置@property为标准用户默认对象,这样就不必通过调用来检索standardUserDefaults它(因为看起来你使用它相当多,这可能是你应该走的路)。

这样做:

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

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.userDefaults = [NSUserDefaults standardUserDefaults];
    }
    
  3. 在与您的初始化方法对应的方法中释放用户默认变量(dealloc对于init方法,或viewDidUnload对于viewDidLoad):

    - (void)viewDidUnload
    {
        self.userDefaults = nil;
    }
    
于 2011-12-14T00:40:35.807 回答
2

没有什么可以“声明”的。每次您说[NSUserDefaults standardUserDefaults]您正在访问用户默认值时,无论您从哪里说。如果您需要设置默认默认值(即某些键的初始值),请在您的程序中非常早地进行设置,例如在应用程序委托的applicationDidFinishLaunching中,通过调用registerDefaults.

于 2011-12-14T00:38:44.070 回答
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

现在所有的键都被隐藏了,我NSUserDefaults使用与我的应用程序相关的更好的 API 进行交互。

于 2011-12-14T01:14:04.397 回答