我正在尝试保存一些数据,并从其他控制器的tableview中调用它,但是它不起作用。我也在某种程度上失去了一个变量值,例如当我在视图控制器中更改类别var时,类别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;
}


*******更新**************

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

-(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];


并且表格仍然显示为空白。
谢谢您的帮助。

最佳答案

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

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


发送通知。在Projects.m中的某个位置(初始化是一个不错的地方),使用订阅通知

[[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文件中。我喜欢这种方式的另一件事是它隐藏了实现细节。没有人需要知道特定的字符串是什么,因此不应将其放在头文件中。

关于objective-c - NSUserDefaults不保存,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9417651/

10-14 20:06