我的应用程序中有一个名为SettingsManager的单例,它应该负责读取/写入plist的设置。使用Cocoa With Love(zipped macro file)中的宏来合成Singleton。我只从(void)中将retain的返回类型更改为(oneway void)。这是因为iOS中的新编译器可以处理内存管理。我的问题是每当我调用savePrefs时,按钮调用选择器“挂起”活动状态,有时我得到EXC_BAD_ACCESS。所以我想我的内存管理失败了。令人惊讶的是,当没有可用的plist文件时(在应用程序安装之后),所有默认值都可以从我的NSMutableDictionary中正确存储和检索。以下是我的代码。非常感谢你的帮助。
马丁
CODE:
1 / Singleton标题
#import <Foundation/Foundation.h>
#define SALARY_PREF_KEY @"MonthlySalary"
#define DEFAULT_SALARY [NSNumber numberWithDouble: 0.0]
#define CURRENCY_PREF_KEY @"Currency"
#define DEFAULT_CURRENCY @"USD"
#define EXPENSES_PREF_KEY @"Expenses"
#define DEFAULT_EXPENSES [NSNumber numberWithDouble: 0.0]
#define TIME_INTERVAL_PREF_KEY @"TimeInterval"
#define DEFAULT_INTERVAL [NSNumber numberWithInteger: 2]
#define SAVINGS_PREF_KEY @"Savings"
#define DEFAULT_SAVINGS [NSNumber numberWithDouble: 0.0]
@interface SettingsManager : NSObject {
NSString *prefsFilePath;
NSMutableDictionary *settingsDictionary;
NSNumber *salary;
NSString *currency;
NSNumber *expenses;
NSNumber *timeInterval;
NSNumber *savings;
}
+ (SettingsManager *)sharedSettingsManager;
@property (nonatomic, retain) NSString *prefsFilePath;
@property (nonatomic, retain) NSMutableDictionary *settingsDictionary;
@property (nonatomic, retain) NSNumber *salary;
@property (nonatomic, retain) NSString *currency;
@property (nonatomic, retain) NSNumber *expenses;
@property (nonatomic, retain) NSNumber *timeInterval;
@property (nonatomic, retain) NSNumber *savings;
- (void) savePrefs;
@end
2 /实施:
#import "SynthesizeSingleton.h"
#import "SettingsManager.h"
@implementation SettingsManager
SYNTHESIZE_SINGLETON_FOR_CLASS(SettingsManager);
@synthesize settingsDictionary,
salary,
currency,
expenses,
timeInterval,
savings,
prefsFilePath;
- (id)init {
self = [super init];
if (self) {
if (prefsFilePath == nil) {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
prefsFilePath = [documentsDirectory stringByAppendingPathComponent:@"iEarn.plist"];
}
if ([[NSFileManager defaultManager] fileExistsAtPath: prefsFilePath]) {
settingsDictionary = [[NSMutableDictionary alloc]
initWithContentsOfFile: prefsFilePath];
}
else {
settingsDictionary = [[NSMutableDictionary alloc] initWithCapacity: 7];
[settingsDictionary setObject: DEFAULT_SALARY forKey: SALARY_PREF_KEY];
[settingsDictionary setObject: DEFAULT_CURRENCY forKey: CURRENCY_PREF_KEY];
[settingsDictionary setObject: DEFAULT_EXPENSES forKey: EXPENSES_PREF_KEY];
[settingsDictionary setObject: DEFAULT_INTERVAL forKey: TIME_INTERVAL_PREF_KEY];
[settingsDictionary setObject: DEFAULT_SAVINGS forKey: SAVINGS_PREF_KEY];
[settingsDictionary writeToFile: prefsFilePath atomically: YES];
}
self.salary = [settingsDictionary objectForKey:SALARY_PREF_KEY];
self.currency = [settingsDictionary objectForKey:CURRENCY_PREF_KEY];
self.expenses = [settingsDictionary objectForKey:EXPENSES_PREF_KEY];
self.timeInterval = [settingsDictionary objectForKey:TIME_INTERVAL_PREF_KEY];
self.savings = [settingsDictionary objectForKey:SAVINGS_PREF_KEY];
}
return self;
}
- (void) savePrefs {
[settingsDictionary setObject: salary forKey: SALARY_PREF_KEY];
[settingsDictionary setObject: currency forKey: CURRENCY_PREF_KEY];
[settingsDictionary setObject: expenses forKey: EXPENSES_PREF_KEY];
[settingsDictionary setObject: timeInterval forKey: TIME_INTERVAL_PREF_KEY];
[settingsDictionary setObject: savings forKey: SAVINGS_PREF_KEY];
[settingsDictionary writeToFile: prefsFilePath atomically: YES];
}
- (void) dealloc {
[settingsDictionary dealloc];
[super dealloc];
}
@end
3 /我如何致电savePrefs
- (IBAction)saveButtonPressed:(id)sender {
[[SettingsManager sharedSettingsManager] setSalary: [NSNumber numberWithDouble: [salary.text doubleValue]]];
[[SettingsManager sharedSettingsManager] setCurrency: currency.text];
[[SettingsManager sharedSettingsManager] setExpenses: [NSNumber numberWithDouble: [expenses.text doubleValue]]];
[[SettingsManager sharedSettingsManager] setTimeInterval: [NSNumber numberWithInt: [intervalStepper value]]];
[[SettingsManager sharedSettingsManager] setSavings: [NSNumber numberWithDouble: [savings.text doubleValue]]];
[[SettingsManager sharedSettingsManager] savePrefs];
}
答案 0 :(得分:1)
您似乎直接访问prefsFilePath
实例变量而不是使用其访问者:
prefsFilePath = [documentsDirectory stringByAppendingPathComponent:@"iEarn.plist"];
存储的值是自动释放的,因此在当前池耗尽后,引用不再有效。相反,你应该使用:
self.prefsFilePath = [documentsDirectory stringByAppendingPathComponent:@"iEarn.plist"];
或
prefsFilePath = [[documentsDirectory stringByAppendingPathComponent:@"iEarn.plist"] retain];
注意:您可以为所有属性访问添加前缀以避免出现问题,或rename the instance variables。