NSUserDefaults没有保存

时间:2012-02-23 17:05:17

标签: objective-c ios uitableview nsuserdefaults

我正在尝试保存一些数据,并在不同控制器的tableview中将其调回,但它无效。我在某种程度上也失去了一个变量值,就像我在视图控制器中更改它时类别var变回零一样。

在我的NewEntry.m中,我有:

-(IBAction)saveButton:(id)sender {    

    int i = selectedSegment.selectedSegmentIndex;    

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    [userDefaults setInteger:i  forKey:@"category"];

    [userDefaults synchronize];

    if (selectedSegment.selectedSegmentIndex == 0) {
        [userDefaults setObject:titlefield.text forKey:@"titletexthomework"];
        [userDefaults setObject:detailstextfield.text forKey:@"detailshomework"];
    }
    else if(selectedSegment.selectedSegmentIndex == 1) {
        [userDefaults setObject:titlefield.text forKey:@"titletextprojects"];
        [userDefaults setObject:detailstextfield.text forKey:@"detailsprojects"];

    }
    else if (selectedSegment.selectedSegmentIndex == 2){
        [userDefaults setObject:titlefield.text forKey:@"titletextappointments"];
        [userDefaults setObject:detailstextfield.text forKey:@"detailsappointments"];
    }
    else if (selectedSegment.selectedSegmentIndex == 3){
        [userDefaults setObject:titlefield.text forKey:@"titletextevents"];
        [userDefaults setObject:detailstextfield.text forKey:@"detailsevents"];

    }

    else if (selectedSegment.selectedSegmentIndex == 4){
        [userDefaults setObject:titlefield.text forKey:@"titletexttodolist"];
        [userDefaults setObject:detailstextfield.text forKey:@"detailstodolist"];
    }

    [userDefaults synchronize];
    NSLog(@"selected segment %i", i);
}

然后在我的Projects.m中我有:

-(void)viewDidLoad
{
    [super viewDidLoad];    

    categoryselected = [[NSUserDefaults standardUserDefaults] integerForKey:@"category"];
    NSLog(@"category selected %i", categoryselected);        

    titlestring = [[NSUserDefaults standardUserDefaults]  objectForKey:@"titletextprojects"];
    detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:@"detailsprojects"];        

    tabledata = [[NSArray alloc] initWithObjects:titlestring, nil];
    tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil];    
}

//-------------------------------------------------------
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{    
    UITableViewCell *cell = nil;

    cell = [tableView dequeueReusableCellWithIdentifier:@"projectscell"];   

    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"projectscell"];
    }

    cell.textLabel.text = [tabledata objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = [tablesubtitles objectAtIndex:indexPath.row];
    cell.textLabel.font = [UIFont systemFontOfSize:14.0];
    cell.textLabel.backgroundColor = [ UIColor clearColor ];
    cell.detailTextLabel.backgroundColor = [UIColor clearColor];

    return cell;
}

** * ** * * 更新< / EM> * ** * ** * ** * ** * *

我将填充表格的部分更改为静态字符串,如下所示:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
tabl = [[NSArray alloc] initWithObjects:@"hello", nil];
NSLog(@"tabledata %@", tabledata );
tab = [[NSArray alloc] initWithObjects:@"hello2", nil];
NSLog(@"details %@", tablesubtitles);



UITableViewCell *cell = nil;

cell = [tableView dequeueReusableCellWithIdentifier:@"projectscell"];


if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"projectscell"];

}
cell.textLabel.text = [tabl objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [tab objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:14.0];
cell.textLabel.backgroundColor = [ UIColor clearColor ];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];

表格仍显示空白。 谢谢你的帮助。

4 个答案:

答案 0 :(得分:3)

在设置任何值后调用同步。

答案 1 :(得分:1)

我没有注意到NSUserDefaults代码本身有什么问题,尽管它只是在加载视图时抓取值,而不是在值更新时。要解决此问题,您可以发送通知,让所有其他感兴趣的视图控制器知道状态更改。在 - [NewEntry saveButton:]中,在NSUserDefaults中保存值后,添加

[[NSNotificationCenter defaultCenter] postNotificationName:@"ValuesChanged"
                                                    object:self];

发送通知。在Projects.m的某个地方(init是一个好地方),用

订阅通知
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(valuesChanged:)
                                             name:@"ValuesChanged"
                                           object:nil];

这会导致通知中心在发布通知时回调您的valuesChanged:方法。我们将以与viewDidLoad相同的方式更新UI,因此让我们考虑代码:

- (void)reloadData
{
    categoryselected = [[NSUserDefaults standardUserDefaults] integerForKey:@"category"];
    NSLog(@"category selected %i", categoryselected);

    // XXX - note the following strings are returned autoreleased. If they're
    // stored in ivars, it's a good idea to retain them, even though we know
    // they're retained by the arrays below.

    titlestring = [[NSUserDefaults standardUserDefaults]  objectForKey:@"titletextprojects"];
    detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:@"detailsprojects"];

    [tabledata release];
    tabledata = [[NSArray alloc] initWithObjects:titlestring, nil];

    [tablesubtitles release];
    tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil];

    [tableView reloadData];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self reloadData];
}

- (void)valuesChanged:(NSNotification*)notification
{
    [self reloadData];
}

最后一件事:所有这些字符串,NSUserDefaults的密钥和通知名称@“ValuesChanged”?它们确实应该被定义为常量,以便只有一个“真实”版本的字符串。首先,这可以避免您在一个地方意外拼错它的情况,并想知道为什么这些值没有同步。可能需要几个小时才能确定发生这种情况时会发生什么。 (根据这里的经验说。)其次,编译器可以检查您是否具有正确的名称,并且IDE的自动完成(当它实际工作时)可以为您建议密钥名称。你可以在某个地方的共享标题中执行#define

#define kDefaultsKeySelectedCategory @"category"

并且链接器将可能创建在其使用的每个位置之间共享的字符串的单个常量实例。尽管如此,如果我更改了该定义中的字符串并且Xcode是胡思乱想并且不重新编译使用它的每个源文件,我们将回到键在不同位置拼写不同的情况。不好。执行此操作的更高级方法是确保只有一个字符串副本才能声明

extern NSString* const kDefaultsKeySelectedCategory;

在头文件中,然后

NSString* const kDefaultsKeySelectedCategory = @"category";
<。>在.m文件中。我喜欢这种方式的另一件事是它隐藏了实现细节。没有人需要知道具体的字符串是什么,所以它不应该在头文件中。

答案 2 :(得分:0)

当我测试我的应用时遇到了同样的问题,如果我在调试器中使用Stop然后重新启动我的应用,则NSUserDefaults错误地显示旧列表。插入操作不会发生这种情况,但删除操作不会发生这种情况。

如果我使用主页按钮退出应用程序(杀死它),然后重新启动,我的NSUserDefaults是正确的。

Alec 2012年2月23日17:13在之前的评论中也提到了这一点。

答案 3 :(得分:0)

我遇到NSUserDefaults未设置的问题,即使您之后立即使用了synchronize命令。我的问题是因为应用程序已重命名,我相信NSUserDefaults没有正确同步位置。我已经卸载了应用程序,并从Xcode重新安装了它,但它确实有效。我想这有点特殊情况,但如果有的话尝试。