Unable to read NSUserDefaults data between views

Disclaimer: major noob

I am writing an arithmetic application for flash cards as a training project. I have a UITabViewController with a bottom tab bar that switches between several different views. Everything works fine until I try to set the logical values ​​of NSUserDefault in the settings view controller and try to read these values ​​in the Flashcards view controller.

In the settings window, there is a switch for turning on / off each operator (addition, subtraction, etc.), and in flash card mode, a flash card is randomly displayed if this type of operation was turned on.

I believe that my mistake is that I do not understand the key concept of encapsulating data, objects, etc. I would appreciate any help.

Here is the settings view controller. I'm not even sure how to put the code on this forum, so this might be a funny moment ... here goes:

//  settings_flashcards.h

#import <UIKit/UIKit.h>
@interface settings_flashcards : UIViewController {
UISwitch *additionSwitch;
UISwitch *subtractionSwitch;
UISwitch *multiplicationSwitch;
UISwitch *divisionSwitch;
}

@property (nonatomic,retain) IBOutlet UISwitch *additionSwitch;
@property (nonatomic,retain) IBOutlet UISwitch *subtractionSwitch;
@property (nonatomic,retain) IBOutlet UISwitch *multiplicationSwitch;
@property (nonatomic,retain) IBOutlet UISwitch *divisionSwitch;

@end

and...

/  settings_flashcards.m

#import "settings_flashcards.h"

@implementation settings_flashcards

@synthesize additionSwitch;
@synthesize subtractionSwitch;
@synthesize multiplicationSwitch;
@synthesize divisionSwitch;

- (void)viewDidLoad {

[additionSwitch addTarget:self action:@selector(additionSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[subtractionSwitch addTarget:self action:@selector(subtractionSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[multiplicationSwitch addTarget:self action:@selector(multiplicationSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[divisionSwitch addTarget:self action:@selector(divisionSwitchFlipped) forControlEvents:UIControlEventValueChanged];
[super viewDidLoad];
}

-(void) additionSwitchFlipped {
if (additionSwitch.on) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"additionKey"];
}else {
    [[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:@"additionKey"];
}
}

-(void) subtractionSwitchFlipped {
if (subtractionSwitch.on) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"subtractionKey"];  
}else {
    [[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:@"subtractionKey"]; 
}
}

-(void) multiplicationSwitchFlipped {
if (multiplicationSwitch.on) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"multiplicationKey"];   
}else {
    [[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:@"multiplicationKey"];  
}

}

-(void) divisionSwitchFlipped {
if (divisionSwitch.on) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"divisionKey"]; 
}else {
    [[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:@"divisionKey"];    
}
}

Here is a presentation of Flashcards ...

//  flashcardsViewController.h

#import <UIKit/UIKit.h>

@interface flashcardsViewController : UIViewController <UIActionSheetDelegate>{

UILabel *firstNumberLabel;
UILabel *secondNumberLabel;
UILabel *answerNumberLabel;
UILabel *operatorLabel;

BOOL additionIsEnabled;
BOOL subtractionIsEnabled;
BOOL multiplicationIsEnabled;
BOOL divisionIsEnabled;
}

@property (nonatomic,retain) IBOutlet UILabel *firstNumberLabel;
@property (nonatomic,retain) IBOutlet UILabel *secondNumberLabel;
@property (nonatomic,retain) IBOutlet UILabel *answerNumberLabel;
@property (nonatomic,retain) IBOutlet UILabel *operatorLabel;

-(void) buttonClicked:(id)sender;

@end

and...

//  flashcardsViewController.m

#import "flashcardsViewController.h"

@implementation flashcardsViewController

@synthesize firstNumberLabel;
@synthesize secondNumberLabel;
@synthesize answerNumberLabel;
@synthesize operatorLabel;

- (void)viewDidLoad {

srand(time(0)); //seed random

//the following should assign the keys if they don't exist  
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"additionKey"]){
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"additionKey"];
}   


if (![[NSUserDefaults standardUserDefaults] boolForKey:@"subtractionKey"]) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"subtractionKey"];
}

if (![[NSUserDefaults standardUserDefaults] boolForKey:@"multiplicationKey"]) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"multiplicationKey"];

}

if (![[NSUserDefaults standardUserDefaults] boolForKey:@"divisionKey"]) {
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"divisionKey"];
}

//the following should assign each BOOL variable based on the key
additionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"additionKey"];
subtractionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"subtractionKey"];
multiplicationIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"multiplicationKey"];
divisionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"divisionKey"];
[super viewDidLoad];
}

-(void) buttonClicked:(id)sender{

int a = rand() %  4;// random number generator (number to enter loop)   

if ( additionIsEnabled || subtractionIsEnabled || multiplicationIsEnabled || divisionIsEnabled) {
    while (a < 5) {
        switch (a) {
            case 0:
                if (additionIsEnabled == TRUE){
                    int x = rand() % 11 + 1;
                    int y = rand() %11 + 1;
                    firstNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",x];
                    secondNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",y];
                    answerNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",(x+y)];
                    operatorLabel.text = [[NSString alloc]initWithFormat: @"+"];
                    a = 5;
                }
                else a++;
                break;
            case 1:
                if (subtractionIsEnabled == TRUE){
                    int x = rand() % 19 + 1;
                    int y = rand() %11 + 1;
                    firstNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",x];
                    secondNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",y];
                    answerNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",(x-y) ];
                    operatorLabel.text = [[NSString alloc]initWithFormat: @"-"];
                    a = 5;
                }
                else a++;
                break;
            case 2:
                if (multiplicationIsEnabled == TRUE){
                    int x = rand() % 11 + 1;
                    int y = rand() %11 + 1;
                    firstNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",x];
                    secondNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",y];
                    answerNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",(x*y)];
                    operatorLabel.text = [[NSString alloc]initWithFormat: @"×"];
                    a = 5;
                }
                else a++;
                break;
            case 3:
                if (divisionIsEnabled == TRUE){
                    int x = rand() % 11 + 1;
                    int y = rand() % 11 + 1;
                    firstNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",(x*y)];
                    secondNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",y];
                    answerNumberLabel.text = [[NSString alloc]initWithFormat: @"%i",x];
                    operatorLabel.text = [[NSString alloc]initWithFormat: @"÷"];
                    a = 5;
                }
                else a = 0;
                break;
                default:
                break;
        }
    }       
}
else
{
    UIAlertView *noOperatorSelectedAlert = [[UIAlertView alloc]initWithTitle:@"You have not set any operations."
                                                   message:@"Return to the settings menu and decide which operations you wish to perform. (addition, subtraction, etc.)"
                                                   delegate:self
                                                   cancelButtonTitle:@"Ok" 
                                                   otherButtonTitles:nil];
    [noOperatorSelectedAlert show];
    [noOperatorSelectedAlert release];
}
}
+3
source share
3 answers

There are a few things here. First, you need a better way of saying what the default state is before the user makes any explicit decisions. Then you want to know when you should update your state in the application from user settings.

Default initialization

. , , , . , , , . ( "x" ) .

API, , -[NSUserDefaults registerDefaults:], NSDictionary. YES ( Objective-C BOOL YES NO, TRUE FALSE), - , +initialize :

+ (void) initialize
{
    // in any +initialize, make sure it being called on your class
    // +initialize is different from all other methods in this respect
    if ( [self isKindOfClass: [MyApplicationDelegate class]] == NO )
        return;    // being called on a superclass, don't do my stuff

    // set up default values for certain preferences
    NSMutableDictionary * defaults = [NSMutableDictionary new];
    [defaults setObject: [NSNumber numberWithBool: YES] forKey: @"additionKey"];
    [defaults setObject: [NSNumber numberWithBool: YES] forKey: @"subtractionKey"];
    [defaults setObject: [NSNumber numberWithBool: YES] forKey: @"multiplicationKey"];
    [defaults setObject: [NSNumber numberWithBool: YES] forKey: @"divisionKey"];

    // set this as the registration domain
    [[NSUserDefaults standardUserDefaults] registerDefaults: defaults];
    [defaults release];
}

, , , , +initialize.

, [[NSUserDefault standardUserDefaults] boolForKey: @"additionKey"], , , .

, , . , , - . . :

  • NSUserDefaults, . , .
  • NSUserDefaults , .

, flashcardsViewController - :

- (void) updateFromPreferences
{
    // fetch current values from user defaults into your member variables
    additionIsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey: @"additionKey"];
    // etc...
}

- (void) viewWillLoad
{
    // load variables from user defaults
    [self updateFromPreferences];

    // find out when the preferences have been changed
    // this will cause -updateFromPreferences to be called
    // whenever something changes preferences, inside the app or outside
    [[NSNotificationCenter defaultNotificationCenter] addObserver: self
                                                         selector: @selector(updateFromPreferences)
                                                             name: NSUserDefaultsDidChangeNotification
                                                           object: nil];
}

- (void) viewDidUnload
{
    // always remove notification observers.
    [[NSNotificationCenter defaultNotificationCenter] removeObserver: self
                                                                name: NSUserDefaultsDidChangeNotification
                                                              object: nil];
}

- (void) dealloc
{
    // add this to your existing dealloc routine
    [[NSNotificationCenter defaultNotificationCenter] removeObserver: self
                                                                name: NSUserDefaultsDidChangeNotification
                                                              object: nil];
}

, .

+5

" ", , -buttonClicked: NSUserDefaults. ( ) [flashcardsViewController viewDidLoad]. , flashCardsViewController (, ).

- IsEnabled BOOL -buttonClicked, :

-(void) buttonClicked:(id)sender {

    // the following should assign each BOOL variable based on the key
    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
    additionIsEnabled = [defaults boolForKey:@"additionKey"];
    subtractionIsEnabled = [defaults boolForKey:@"subtractionKey"];
    multiplicationIsEnabled = [defaults boolForKey:@"multiplicationKey"];
    divisionIsEnabled = [defaults boolForKey:@"divisionKey"];

    int a = rand() %  4;
    if ( additionIsEnabled || subtractionIsEnabled ...
+4

...

//the following should assign the keys if they don't exist  
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"additionKey"]){
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"additionKey"];
}

... additionKey TRUE. , additionKey, ...

//the following should assign the keys if they don't exist  
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"additionKey"]){
    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:@"additionKey"];
}

... boolForKey: documentation: , . NO.

- , additionKey, . , NO/FALSE.

So, your code does this - if the value is not related to additionKeyor if it is set to NO, set it to YES. This leads to this - additionKeyalways set to YES / TRUE.

+3
source

Source: https://habr.com/ru/post/1794798/


All Articles