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

时间:2015-01-05 23:47:10

标签: objective-c uitableview save nsuserdefaults checkmark

解决方案!!

感谢Josh的耐心:D

因此,初始问题中的代码始终勾选所选单元格并取消选择先前选定的单元格而不保存任何内容到NSUserDefaults。在Josh的大量帮助之后,新代码(右下方)如下(与他的回复完全相同/我只是稍微清理了一下并删除了之前尝试使其工作的@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

2 个答案:

答案 0 :(得分:0)

代码中的哪个位置保存用户默认值?

didSelectRowAtIndexPath中,您可以添加:

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

cellForRowAtIndexPath中,您可以查看是否

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

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

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

修改 要扩展最终注释,您可以执行以下操作:

在界面中......

@property (nonatomic) int selectedRow;

在实施中......

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

只要在头文件中声明selectedRow属性,您就可以将此代码放在viewWillAppearviewDidAppear甚至prepareForSegue中的前一个视图控制器中。 。我不会将此代码放在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>
    }
 }

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

当用户选择其他行时,您可以更新selectedSetting属性,然后在viewWillDisappearprepareForSegue中(即在展开segue之前),您可以更新standardUserDefaults。

答案 1 :(得分:0)

#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