在 NSUserDefaults 中保存复选标记 - 动态 TableView

Save checkmark in NSUserDefaults - dynamic TableView

解决方法!!

感谢 Josh 的耐心等待 :D

所以初始问题中的代码总是勾选选定的单元格并取消选择先前选定的单元格而不将任何内容保存到 NSUserDefaults。在 Josh 的大量帮助之后,新代码(右下方)如下(与他的 reply/I 中的代码完全相同,只是将其清理了一点并删除了之前尝试中定义的 @properties 以使其工作)。

用户点击 7 个单元格中的一个。点击的单元格的 indexPath 然后保存在 NSUserdefaults 中,当 TableView 再次打开时,先前点击的单元格旁边会显示一个复选标记。索引路径始终保存在同一个 NSObject 中,因此只会显示一个复选标记。

#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"

@interface CycleTableViewController ()
@property (nonatomic) int selectedRow;
@end

@implementation CycleTableViewController
@synthesize array;

- (void)viewDidLoad {
    //load array containing options
    array=@[@"1", @"2",  @"3", @"4", @"5", @"6", @"7"];

    [super viewDidLoad];
    }

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

- (void) viewWillDisappear:(BOOL)animated{
    //save indexpath of tapped cell to NSUserdefaults
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    }

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
    }

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [array count];
    }

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIndentifier=@"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];

    cell.textLabel.text = [array objectAtIndex:indexPath.row];
   
    //display checkmark next to the tapped cell
    if(indexPath.row == self.selectedRow){
       cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
    else{
       ell.accessoryType = UITableViewCellAccessoryNone;
        }         
        return cell;
    }

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //assign indexpath to selectedRow, so NSUserdefaults can save them
    self.selectedRow = indexPath.row;        
    [self.tableView reloadData];
    }

    //save indexpath of tapped cell to NSUserdefaults
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];

@end


初始问题

我在这里阅读了大量关于将索引路径保存到用户默认值的帖子,但没有一个对我有用...

在下面的 TableView 中,我显示了一个数据数组 (1-7),然后在按下一个单元格后将其传递给另一个 ViewController。按下的单元格得到一个复选标记,如果我返回使用导航控制器,我可以看到复选标记。一次只能选择一项。如果我按另一行,复选标记会改变。

所以现在我想将所选行的索引路径保存到 UserDefaults(在 didselectrowat indexpath 中)并将其加载到 viewdidload 但我总是得到 build failed ,无论我尝试...

有人能给我指出正确的方向吗?这应该很容易,但我就是无法让它工作:/

更新代码!一旦我开始工作,我会上传完成的答案!

#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"


@interface CycleTableViewController (){
    NSString *currentCategory; // pointer to the currently checked item
}
// other @property declarations here or in your .m file
#define CHECKED_KEY @"kCheckedBoxKey"

@property (nonatomic) int selectedRow;



@end

@implementation CycleTableViewController
@synthesize array;



- (void)viewDidLoad {
    
    //load tickmark according to newCell;
    
    array=@[@"21+7", @"22+6",  @"23+5", @"24+4", @"25+3", @"26+2", @"28"];

    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
-(void) viewWillAppear:(BOOL)animated {
    self.selectedRow = [[[NSUserDefaults standardUserDefaults] objectForKey:@"cycle"] intValue];
    
 }

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [array count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIndentifier=@"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];
    
    cell.textLabel.text = [array objectAtIndex:indexPath.row];
    
    return cell;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    NSIndexPath *IndexPath = [NSIndexPath indexPathForRow:self.selectedRow inSection:0];
    UITableViewCell *Cell = [tableView cellForRowAtIndexPath:IndexPath];
    Cell.accessoryType = UITableViewCellAccessoryCheckmark;
    
}

@end

您将用户默认值保存在代码的什么位置?

didSelectRowAtIndexPath 中,您可以添加:

[[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"nameOfSetting"];
[[NSUserDefaults standardUserDefaults] synchronize];

cellForRowAtIndexPath 你可以检查是否

indexPath.row == [[[NSUserDefaults standardUserDefaults] objectForKey:@"nameOfSetting"] intValue]

如果是,请添加复选标记配件。如果没有,则不显示配件。

请注意,我实际上会创建一个 属性 来保存 selectedValue,只有在离开设置页面或点击保存按钮后,您才会真正更新用户默认值。然后在 viewWillAppear 中,我会将此 属性 设置为等于用户默认设置中的设置,并在 table.

上调用重新加载

编辑 要扩展最后的注释,您可以执行以下操作:

在界面中...

@property (nonatomic) int selectedRow;

实施中...

self.selectedRow = [[NSUserDefaults standardUserDefaults] objectForKey:@"nameOfsetting"] intValue];

您可以将此代码放在 viewWillAppearviewDidAppear 甚至 prepareForSegue 中,只要 selectedRow 属性在头文件中声明。我不会将此代码放在 viewDidLoad.

然后在 cellForRowAtIndexPath 中单独添加如下内容:

if(indexPath.row == self.selectedRow){
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
    cell.accessoryType = UITableViewCellAccessoryNone;
}

编辑#2

在显示当前设置的 OptionsViewController 中,您可以从 standardUserDefaults 加载设置。你可以像我提到的那样保存一个数字作为设置(即如果你有设置选项,你可以将它们编号为 0 - 6 并使用 typedef 使代码更清晰)或者你可以存储一个字符串。如果将设置存储为数字,则只需要一本字典将数字映射到设置说明。如果将设置存储为字符串,则可以只显示该字符串。

无论选择哪种方法,在 OptionsViewController 中执行此操作:

#import "SettingsViewController.h"

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
   if([segue.destinationViewController isKindOfClass:[SettingsViewController class]]){
       SettingsViewController *settingsViewController = (SettingsViewController *) segue.destinationViewController;
       settingsViewController.selectedSetting= <INSERT YOUR SETTING FROM STANDARDUSERDEFAULTS>
    }
 }

基本上,您是将设置从选项移交给包含您的 table 的设置视图。您可以将 SettingsViewController 中的 selectedSetting 设为数字或字符串,如上所示。正如某些点,您必须将您的设置转换为数字,以便 table 知道哪一行有复选标记。我会保持其余代码不变,即 cellForRowAtIndexPath 中的 if 语句。您需要以某种方式检查 indexPath.row 是否与 selectedSetting 匹配(即,如果它是字符串,则需要将其转换为数字)。并在 viewWillAppearviewDidAppear 中重新加载 table 视图,以便显示复选标记。

当用户选择不同的行时,您可以更新 selectedSetting 属性,然后在 viewWillDisappearprepareForSegue(即展开转场之前)您可以更新 standardUserDefaults。

#import "CycleTableViewController.h"
#import "SettingsTableViewController.h"


@interface CycleTableViewController (){
    NSString *currentCategory; // pointer to the currently checked item
}
// other @property declarations here or in your .m file
#define CHECKED_KEY @"kCheckedBoxKey"

@property (nonatomic) int selectedRow;

@end

@implementation CycleTableViewController
@synthesize array;

- (void)viewDidLoad {

    //load tickmark according to newCell;

    array=@[@"21+7", @"22+6",  @"23+5", @"24+4", @"25+3", @"26+2", @"28"];

    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) viewWillAppear:(BOOL)animated {
    self.selectedRow = [[[NSUserDefaults standardUserDefaults] objectForKey:@"cycle"] intValue];        
 }

- (void) viewWillDisappear:(BOOL)animated{
    [[NSUserDefaults standardUserDefaults] setObject:@(indexPath.row) forKey:@"cycle"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [array count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIndentifier=@"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIndentifier forIndexPath:indexPath];

    cell.textLabel.text = [array objectAtIndex:indexPath.row];

    if(indexPath.row == self.selectedRow){
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
     }
    else{
        cell.accessoryType = UITableViewCellAccessoryNone;
    }         
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     self.selectedRow = indexPath.row;        
     [self.tableView reloadData];
}

@end