0

グローバル変数のようなものを使用する最もクリーンな方法はどれですか?通常、グローバル変数の使用は禁止されていますが、さまざまなクラスからNSUserDefaultsにアクセスするためのより良い解決策はわかりません。

私は少し読んでこれを思いついた。Contants.hファイルとConstants.mファイルを定義し、必要な場所にそれらを含めます。

 //Constants.h
 #import <Foundation/Foundation.h>


 @interface Constants : NSObject {
  extern NSUserDefaults *settings;
 }

 @end

 //Constants.m
 @implementation Constants

 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"plist"];
 NSDictionary *settingsDict = [NSDictionary dictionaryWithContentsOfFile:filePath];
 [[NSUserDefaults standardUserDefaults] registerDefaults:settingsDict];
 NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];

 @end

ここでの問題は、値を定数に初期化したいということです。Constants.mにはメソッドがありません。それで、私のヘルパー変数もグローバルになりますか?

言及すべきことの1つ:グローバル変数もリリースする必要があると思いますか?

ご協力いただきありがとうございます!

編集:

@ 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

私のAppDelegate.mには、次のものがあります。

// ...
#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

ViewControllerで、値を照会します。

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

それは解決策でしょうか?

4

2 に答える 2

5

グローバル変数を使用する必要はありません。次のように、プロジェクト内の任意のクラスまたはオブジェクトからuserdefaultsにアクセスできます。

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

変更を加えるたびにuserdefaultsを同期する限り、この方法でフェッチされたデータは一貫しています。

于 2010-09-03T16:02:43.743 に答える
1

グローバル変数は禁止されているだけでなく、ObjCのサブセットであるANSIC仕様の必須部分です。gccとllvmはどちらもグローバルを完全にサポートしています。多くの場合、これらは保護されていない値を渡すための最小かつ最速の方法です。

とはいえ、グローバル変数を明示的に使用することは、おそらく問題の解決策ではありません。MVCパラダイムに非常に適した問題があります。すべてのNSDefaultコードをシングルトンモデルクラス(MVCのM)に配置します。これは、最初のアクセス時に自己初期化でき(実装では非表示のグローバルを使用する場合があります)、そのオブジェクトをappDelegateにアタッチします。どこでも。次に、デフォルト値の読み取り/書き込みをすべてそのオブジェクトのプロパティとしてカプセル化します。

于 2010-09-03T17:47:16.013 に答える