这是使用类似全局变量的最干净的方法吗?通常,禁止使用全局变量,但我不知道从不同类访问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中没有方法。所以我的辅助变量也是全局变量?
有一点需要提及:我认为全局变量也必须被释放?
感谢您的帮助!
修改
@ 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"];
这会是一个解决方案吗?
答案 0 :(得分:5)
您不需要使用全局变量 - 您可以从项目中的任何类或对象访问userdefaults,如下所示:
BOOL foo = [[NSUserDefaults standardUserDefaults] boolForKey:@"bar"];
只要您在每次更改后同步userdefaults,以这种方式获取的数据都是一致的。
答案 1 :(得分:1)
全局变量不仅不被禁止,而且是ANSI C规范的必需部分,它是Obj C的子集.gcc和llvm都完全支持全局变量。它们通常是传递无保护值的最小和最快的方式。
也就是说,明确使用全局变量很可能不是解决问题的方法。你有一个非常适合MVC范例的问题。将所有NSDefault代码放入一个单独的模型类(MVC的M),它可以在第一次访问时自我初始化(实现可能使用隐藏的全局),并将该对象附加到appDelegate,在那里可以很容易地从任何地方。然后将所有默认值read / writes封装为该对象的属性。