Как реализовать NSUserDefault для доступа через несколько представлений

Я пытаюсь поделиться строками и целыми числами в нескольких представлениях для финального проекта вводного курса разработки iOS, около 50, и мне интересно, как бы я это сделал... Я знаю, что парадигма MVC лучше, но мы этого не сделали. не добраться до очень продвинутых вещей, особенно основных данных. Я думал об использовании NSUserDefaults, я знаю, что это неправильно, но это приложение не должно быть невероятно быстрым, и я думаю, что это будет самый простой способ для меня. Мой вопрос: где и как я могу объявить объект NSUserDefault, который я буду использовать? Единственный раз в классе, когда мы использовали его, был в одном представлении. Если я объявлю его в первом загруженном представлении, я знаю, что могу получить к нему доступ с другими представлениями, но нужно ли мне импортировать файл заголовка первого представления в каждое из других или оно будет доступно независимо?


Обновлять


Поэтому я решил упростить задачу, сделав NSUserDefaults свойством всех ViewControllers. Затем, чтобы попытаться вернуть значения, я внедрил заголовки из каждого из ViewControllers в представление, которому требуется доступ к данным, хранящимся в NSUserDefaults (которое также имеет свойство NSUserDefault). Приложение работает ужасно, пока я не доберусь до этого экрана и ничего не обновится. Я уверен, что моя ошибка заключается где-то в том, как я реализовал NSUserDefaults, но я не уверен, как это сделать правильно. Когда мы проходили их в классе (на самом деле это направленное исследование с «Sam's Teach Yourself iPhone Application Development in 24 Hrs» (тошнит, меня это бесит)), единственный раз, когда мы использовали их, было приложение с одним представлением, которое изменило альфа белого фона, чтобы его можно было использовать в качестве фонарика. Вот как это было представлено:

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 здесь, в Миннесоте. Как я могу это сделать? Мне тоже жаль, что, возможно, придется четко указать, как это реализовать.


person JustLikeThat    schedule 14.12.2011    source источник


Ответы (3)


Преимущество 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;
    }
    
person Community    schedule 14.12.2011
comment
Не могли бы вы привести примеры того, как это сделать? Я пробовал все, что мог придумать, и задокументировал это выше в своих обновлениях, но все равно не повезло. - person JustLikeThat; 14.12.2011

Нечего "декларировать". Каждый раз, когда вы говорите [NSUserDefaults standardUserDefaults], вы получаете доступ к пользовательским настройкам по умолчанию, независимо от того, откуда вы это говорите. Если вам нужно установить значения по умолчанию (т. е. начальные значения для определенных клавиш), сделайте это очень-очень рано в своей программе, например. в делегате приложения applicationDidFinishLaunching, вызвав registerDefaults.

person matt    schedule 14.12.2011

Если вы часто используете 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, соответствующий моему приложению.

person Paul.s    schedule 14.12.2011