如何解决NSUserDefaults正确使用并检测更改
| 我是一个初学者,正在构建一个iOS Universal应用程序,该应用程序在应用程序生命周期的各个阶段都使用NSUserDefaults-包括用于设置这些变量的应用程序内页面。我发现我的UserDefaults通常与UI不同步,并且编写代码来检查这些首选项很繁琐。 正如您在下面看到的那样,我正在检查“使用相机”偏好设置是否设置过高;一定有更简单的方法...? 当加载允许在应用程序中编辑用户首选项的viewController时,Get \更糟糕: 是否有某种方法可以消除一些代码量(从而最大程度地减少调试/对内存优化的工作量),而不必经常检查首选项的值是多少?我是否应该使用NSUserDefaultsDidChangeNotification检测到更改,并在此通知方法内设置AppDelegate变量一次? 示例(明显的省略假定存在这些方法...与我的偏好无关: 在我的AppDelegate中:#progma mark Application Lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// check values; if not present,set some defaults.
if (![prefs stringForKey:@\"pfUseCamera\"]) {
[prefs setValue:@\"NO\" forKey:@\"pfUseCamera\"];
}
if (![prefs stringForKey:@\"pfWorkInBackground\"]) {
[prefs setValue:@\"NO\" forKey:@\"pfWorkInBackground\"];
}
[prefs synchronize];
self.backgroundTasksTimer = [NSString stringWithString:[prefs stringForKey:@\"pfWorkInBackground\"]];
self.shouldUseCamera = [NSString stringWithString:[prefs stringForKey:@\"pfUseCamera\"]];
// start our timer
// chose to run this timer ALL-the-time,dispite the user-preference; instead,see below that the timer method returns based on the user preference.
[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(backgroundTasks:) userInfo:nil repeats:YES];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// pretty much the same as above
// except NSTimer,which is controlled elsewhere
}
#progma mark AppDelegate-controlled Methods
- (void)backgroundTasks:(NSTimer *)timer {
if (![self.backgroundTasksTimer boolValue]) {
return;
} else {
// do stuff in a timer begun in AppDelegate only if this preference is NOT NO
}
}
我的主要ViewController:
#progma mark ViewController Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
MyAppDelegate *app = [MyAppDelegate sharedAppDelegate]; // I have this set up in the AppDelegate to allow this
if ([app.shouldUseCamera boolValue]) {
// init the camera and have it ready for use
}
}
- (void)viewDidAppear:(BOOL)animated {
MyAppDelegate *app = [MyAppDelegate sharedAppDelegate]; // I have this set up in the AppDelegate to allow this
if ([app.shouldUseCamera boolValue]) {
// resume the camera capture
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
MyAppDelegate *app = [MyAppDelegate sharedAppDelegate];
if ([app.shouldUseCamera boolValue]) {
// suspend the camera capture
}
}
- (void)viewDidUnload {
MyAppDelegate *app = [MyAppDelegate sharedAppDelegate];
if ([app.shouldUseCamera boolValue]) {
// unload the camera
}
}
#progma mark User/IBAction Methods
-(IBAction)doStuff:(id)sender {
MyAppDelegate *app = [MyAppDelegate *app = [MyAppDelegate sharedAppDelegate]; sharedAppDelegate];
// take a picture
if ([app.shouldUseCamera boolValue]) {
[NSThread detachNewThreadSelector:@selector(takePicture:) toTarget:self withObject:fileName]; // take a photo and do stuff to it in a separate thread
}
}
SettingsViewController:
- (void)viewDidLoad {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
MyAppDelegate *app = [MyAppDelegate sharedAppDelegate];
// set UITextField to value of String Preference
someUITextField.text = [prefs stringForKey:@\"pfSomeOtherValue\"];
// set UISwitch to value of PSToggleSwitchSpecifier
if ([app.backgroundTasksTimer boolValue]) {
[shouldExecuteBackgroundTasks setOn:YES];
} else {
[shouldExecuteBackgroundTasks setOn:NO];
}
// set UISwitch to value of PSToggleSwitchSpecifier
if ([app.shouldUseCamera boolValue]) {
[shouldUseCamera setOn:YES];
} else {
[shouldUseCamera setOn:NO];
}
- (IBAction)done:(id)sender {
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
MyAppDelegate *app = [MyAppDelegate sharedAppDelegate];
[prefs setObject:companyID.text forKey:@\"pfCompanyID\"];
if ([shouldUseCamera isOn]) {
[prefs setObject:@\"YES\" forKey:@\"pfUseCamera\"];
app.backgroundTasksTimer = @\"YES\";
} else {
[prefs setObject:@\"NO\" forKey:@\"pfUseCamera\"];
app.backgroundTasksTimer = @\"NO\";
}
if ([shouldExecuteBackgroundTasks isOn]) {
[prefs setObject:@\"YES\" forKey:@\"pfWorkInBackground\"];
app.shouldUseCamera = @\"YES\";
} else {
[prefs setObject:@\"NO\" forKey:@\"pfWorkInBackground\"];
app.shouldUseCamera = @\"NO\";
}
[prefs synchronize];
[self.delegate settingsControllerDidFinish:self];
}
解决方法
一种方法是摆脱应用程序委托中的字段,而仅使用NSUserDefaults。我不确定这样做的开销,但是有一个带有静态访问器的“ Config \”类。另外,您可以考虑使用bool(和其他)访问器,例如:
@implementation Config
+(BOOL)shouldUseCamera {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
return [defaults boolForKey:@\"shouldUseCamera\"];
}
+(void)setShouldUseCamera:(BOOL)should {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:should forKey:@\"shouldUseCamera\"];
}
然后从任何地方访问这些都是很重要的。我将在同一Config类中使用NSBundle和NSProcessInfo,然后我的应用程序将所有配置放在一个位置。
另外,根据我所读的内容,您通常不必调用同步。
,看一下该主题,该主题通过注册默认更改的更改通知来进行。 Nsuserdefaultschange
如果需要多个视图来检查此值,则可以将该值作为应用程序委托的属性公开,并在需要时检查该属性。应用程序委托将订阅通知,并在触发时重新加载属性值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。