2010-09-03 14 views
0

Quelle est la manière la plus propre d'utiliser quelque chose comme une variable globale? Normalement, l'utilisation d'une variable globale est interdite, mais je ne connais pas de meilleure solution pour accéder à NSUserDefaults depuis différentes classes. Je lis un peu et viens avec ça. Je définis un Contants.h et un fichier Constants.m et les inclut partout où je dois.Comment définir une variable globale de type NSUserDefaults et initialiser une valeur?

. Le problème ici est que je veux initialiser une valeur à ma constante. Je n'ai aucune méthode dans Constants.m. Donc mes variables auxiliaires seraient aussi globales?

Une chose à mentionner: Je pense que la variable globale doit également être libérée?

Merci pour votre aide!

Edit:

@ hotpaw2:

AppBundleSingleton.h:

#import <Foundation/Foundation.h> 


@interface AppBundleSingleton : NSObject { 

} 

+ (AppBundleSingleton *)sharedAppBundleSingleton; 

@end 

AppBundleSingleton.m:

#import "AppBundleSingleton.h" 


static AppBundleSingleton *sharedAppBundleSingleton = nil; 


@implementation AppBundleSingleton 

#pragma mark - 
#pragma mark Singleton methods 

+ (AppBundleSingleton *)sharedAppBundleSingleton { 
    @synchronized(self) { 
     if (sharedAppBundleSingleton == nil) { 
      sharedAppBundleSingleton = [[self alloc] init]; 
     } 
    } 
    return sharedAppBundleSingleton; 
} 

+ (id)allocWithZone:(NSZone *)zone { 
    @synchronized(self) { 
     if (sharedAppBundleSingleton == nil) { 
      sharedAppBundleSingleton = [super allocWithZone:zone]; 
      return sharedAppBundleSingleton; // assignment and return on first allocation 
     } 
    } 
    return nil; // on subsequent allocation attempts return nil 
} 

- (id)copyWithZone:(NSZone *)zone { 
    return self; 
} 

- (id)retain { 
    return self; 
} 

- (NSUInteger)retainCount { 
    return NSUIntegerMax; //denotes an object that cannot be released 
} 

- (void)release { 
    //do nothing 
} 

- (id)autorelease { 
    return self; 
} 

-(id)init { 
    self = [super init]; 
    sharedAppBundleSingleton = self; 
    // Initialization code here 
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"plist"]; 
    NSDictionary *settingsDict = [NSDictionary dictionaryWithContentsOfFile:filePath]; 
    [[NSUserDefaults standardUserDefaults] registerDefaults:settingsDict]; 

    return self; 
} 

@end 

Dans mon AppDelegate.m je les suivantes :

// ... 
#include "AppBundleSingleton.h" 


@implementation MyAppDelegate 

// ... 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  

    // Override point for customization after application launch. 

    // Add the navigation controller's view to the window and display. 
    [window addSubview:navigationController.view]; 
    [window makeKeyAndVisible]; 

    [AppBundleSingleton sharedAppBundleSingleton]; 

    return YES; 
} 
// ... 
@end 

Dans mon ViewController je les valeurs: questionne

NSString *myString = [[NSUserDefaults standardUserDefaults] stringForKey:@"myKeyforString"]; 

Serait-ce une solution?

Répondre

1

Les variables globales ne sont pas seulement interdites, mais une partie obligatoire de la spécification ANSI C, qui est un sous-ensemble d'Obj. C. gcc et llvm supportent toutes les variables globales. Ils sont souvent le moyen le plus petit et le plus rapide de transmettre des valeurs non protégées. Cela dit, l'utilisation explicite de variables globales n'est probablement pas la solution à votre problème. Vous avez un problème assez bien adapté au paradigme MVC. Placez tout votre code NSDefault dans une classe de modèle singleton (un M du MVC), qui peut s'auto initialiser lors du premier accès (l'implémentation peut utiliser un global masqué), et attachez cet objet à appDelegate où il peut être facilement obtenu à partir de nulle part. Encapsulez ensuite toutes les valeurs par défaut en lecture/écriture en tant que propriétés de cet objet.

+0

J'ai édité ma question. J'ai maintenant créé un singleton avec une méthode init, qui initialise mon NSUserDefaults à partir d'un fichier plist. Je n'ai plus besoin d'une variable globale. J'accède à mon instance de Singleton dans didFinishLaunchingWithOptions. Est-ce correct? Cela fonctionne jusqu'à présent, mais vous avez mentionné que "certaines vues qui nécessitent une configuration initiale par défaut peuvent être appelées avant appDidFinishLaunching". Comment joindre mon singleton à appDelegate sans utiliser didFinishLaunching? J'appelle directement NSUserDefaults, donc l'obtention de n'importe où est déjà possible. – testing

+0

Le processus d'auto-initialisation est effectué avec l'appel de sharedAppBundleSingleton et la méthode init écrite. Que voulez-vous dire avec les choses d'encapsulation? Ai-je besoin de ces propriétés? Je fais déjà l'initialisation de mes valeurs par défaut dans la méthode init du singleton. – testing

+0

Y a-t-il quelqu'un ici? – testing

5

Vous n'avez pas besoin d'utiliser des variables globales - vous pouvez accéder aux userdefaults de toute classe ou d'un objet dans votre projet comme celui-ci:

BOOL foo = [[NSUserDefaults standardUserDefaults] boolForKey:@"bar"]; 

Tant que vous synchronisez les userdefaults après chaque modification que vous apportez, les données récupérées de cette manière sont cohérentes.

+0

Je veux initialiser mon NSUserDefaults avec ce NSString * filePath = [[NSBundle mainBundle] pathForResource: @ "Paramètres" deType: @ "plist"]; NSDictionary * settingsDict = [NSDictionary dictionaryWithContentsOfFile: filePath]; [[NSUserDefaults standardUserDefaults] registerDefaults: settingsDict]; Où est-ce que je fais ça? – testing

+0

@testing en vous appDidFinishLaunching: méthode –

+0

appDidFinishLaunching peut fonctionner ou non. Certaines vues qui nécessitent une configuration initiale par défaut peuvent être appelées avant appDidFinishLaunching. – hotpaw2