保存、保留和检索数组中的选定单元格

Posted

技术标签:

【中文标题】保存、保留和检索数组中的选定单元格【英文标题】:Saving, retaining, & retrieving selected cells in array 【发布时间】:2016-08-11 02:16:18 【问题描述】:

我已阅读每篇文章并多次尝试每种解决方案,但无法获得正确的功能。

我有一个表格视图,其中包含来自本地 JSON 文件的数据。我需要用户能够:

    选择多个单元格 在选定单元格上显示复选标记 将这些选择写入数组 取消选中时删除选择

5.当用户切换视图或离开并返回表格视图、关闭和重新打开应用程序等时,使用复选标记保存/保留选择。

我已经设法让 1-4 工作,但我被困在 #5 上,无法终生解决这个问题。我已经尽我所能尝试了 NSUserDefaults。任何帮助表示赞赏。以下是当前代码。

另外,为什么我必须双击一个单元格来取消选中它?

@interface FilterViewController () <UISearchResultsUpdating>

@property (nonatomic, strong) NSArray *IngredientsArray;
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) NSMutableArray *searchResults;
@property (nonatomic, strong) NSMutableArray *selectedCell;
@property (nonatomic, strong) NSMutableArray *selectedIngredients;
//I added this property to keep track of the selected row
@property (strong,nonatomic) NSIndexPath *selectedPath;


@end

@implementation FilterViewController 
    NSArray *_locations;





- (void)viewDidLoad 


    [super viewDidLoad];

    self.selectedIngredients = [NSMutableArray array];
     self.selectedCell = [NSMutableArray array];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    self.lastIndexPath = [defaults objectForKey:@"lastIndexPathUsed"];



    // Create a new JSONLoader with a local file URL
    JSONLoaderIngreds *jsonLoader = [[JSONLoaderIngreds alloc] init];
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"locations" withExtension:@"json"];

    // There's no transition in our storyboard to our search results tableview or navigation controller
    // so we'll have to grab it using the instantiateViewControllerWithIdentifier: method
    UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:@"FilterViewSearchResultsNavController"];

    // Our instance of UISearchController will use searchResults
    self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];

    // The searchcontroller's searchResultsUpdater property will contain our tableView.
    self.searchController.searchResultsUpdater = self;


    // create the searchBar programatically.
    self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x,
                                                       self.searchController.searchBar.frame.origin.y,
                                                       self.searchController.searchBar.frame.size.width, 44.0);

    self.tableView.tableHeaderView = self.searchController.searchBar;


    //Sets LocationsViewController as presenter for LocationDetailViewController after searxh results dsiplayed
    //and selected..  Required so searchbar doesn't show in detailsview after segue, and instead, default nav
    //controller back button displays.
    self.definesPresentationContext = true;





    // Load the data on a background queue...
    // As we are using a local file it's not really necessary, but if we were connecting to an online URL then we'd need it
    //NSString *ingreds = [dict objectForKey:@"ingredients"]
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
        _locations = [jsonLoader ingredientsFromJSONFile:url];
        // Now that we have the data, reload the table data on the main UI thread
        [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

        );



// Just before showing the LocationViewController, set the selected Location object
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    LocationsViewController *vc = segue.destinationViewController;
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    vc.location = [_locations objectAtIndex:indexPath.row];



- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];


- (void)viewWillAppear:(BOOL)animated

    //I added this if clause to select the row that was last selected
    if (self.selectedPath != nil) 
        [self.tableView selectRowAtIndexPath:self.selectedPath animated:NO scrollPosition:UITableViewScrollPositionNone];
    



#pragma mark - Table View Controller Methods

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 

     self.selectedPath = indexPath;
    NSString *Ingredient = [_locations objectAtIndex:indexPath.row];
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if([self isRowSelectedOnTableView:tableView atIndexPath:indexPath])
        [self.selectedCell removeObject:indexPath];
        [self.selectedIngredients removeObject:Ingredient];
        cell.accessoryType = UITableViewCellAccessoryNone;
     else 
        [self.selectedCell addObject:indexPath];
        [self.selectedIngredients addObject:Ingredient];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    
    NSLog(@"***************Selected Ingredients**************** %@", self.selectedIngredients);
    NSUserDefaults *userdefaults = [NSUserDefaults standardUserDefaults];
    [userdefaults setObject:[NSString stringWithFormat:@"%ld",(long)indexPath.section] forKey:@"lastIndexPathUsed"];
    [userdefaults synchronize];




-(BOOL)isRowSelectedOnTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath

    return ([self.selectedCell containsObject:indexPath]) ? YES : NO;




- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *unifiedID = @"FilterCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:unifiedID];

    if (!cell) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:unifiedID];
    

    cell.textLabel.text = [_locations objectAtIndex:indexPath.row];
    cell.imageView.image = [UIImage imageNamed:@"ingredientsicon3232.png"];

    //if the indexPath was found among the selected ones, set the checkmark on the cell
    cell.accessoryType = ([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    return cell;






- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return [_locations count];

更新:

我设法按照建议更改了代码,使用下面的更新代码将选择保存到 NSUserDefaults 中的数组,但我仍然无法弄清楚保存/调用复选标记所需的 cellForRowAtIndexPath 代码。

如何编写 cellForRowAtIndexPath 代码来调用复选标记?

使用此代码将选择保存到数组:

ViewDidLoad 代码:

_selections = [NSMutableArray arrayWithArray:(NSArray *)[[NSUserDefaults standardUserDefaults] objectForKey:@"selections"]];
    if(_selections == nil)
        _selections = [[NSMutableArray alloc] init];
    

didSelectRowAtIndexPath 代码:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    
    if ([_selections containsObject: cell.textLabel.text] == NO)
        [_selections addObject:cell.textLabel.text];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
     else 
        [_selections removeObject:cell.textLabel.text];
        cell.accessoryType = UITableViewCellAccessoryNone;
    
    NSLog(@"***************Selected Ingredients**************** %@", _selections);
    NSUserDefaults *userdefaults = [NSUserDefaults standardUserDefaults];

    [userdefaults setObject:_selections forKey:@"selections"];
    [userdefaults synchronize];
    NSLog(@"-------------NSUserDefaults------------%@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation])


【问题讨论】:

【参考方案1】:

您的解决方案非常简单。

    首先,您需要将一组选定的索引路径保存到您的用户默认对象,而不仅仅是最后一次选定的路径。 每当用户选择或取消选择一行时。从同一个数组中添加和删除对象并将其保存回您的用户默认值。 在您的cellForRowAtIndexPath 中,检查您的索引路径是否存在于用户默认值保存的数组中。如果存在,请选择带有复选标记的行,否则保持原样。

希望这会有所帮助。

【讨论】:

我想我明白了,但你能展示一下如何在代码中完成吗?我尝试了几种不同的方法,但无法开始工作。仍然在学习。谢谢。 我现在正在旅行。可能在几个小时后我可以给你看一个例子,但现在你应该尝试这三个步骤,你会明白的。这一点都不难。试一试吧。 按照您的指示,我设法将选择保存到存储在用户默认值中的数组中,但我无法找出保留复选标记的代码。能否提供代码示例? 你能分享你在用户默认值中保存数组的代码吗? 查看相关更新。任何帮助表示赞赏。【参考方案2】:

我认为与其使用indexPath,不如直接使用数据本身,添加Bool 属性以指示Ingredient 类中的选择,然后将整个数组保存在@987654324 @,这样更正确,因为您的数据可以更改,导致您保存的选择indexPath不再正确

【讨论】:

以上是关于保存、保留和检索数组中的选定单元格的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS Swift 中将选定的 tableView 单元格保存到数组中?

iPad:在屏幕上保留选定的表格视图单元格

如何快速检索不同单元格中的数组元素 ios

在屏幕上滚动和返回时如何保留 UITableViewCell 的选定状态

如何从表格视图中的选定单元格中获取文本?

UITableview 在 reloadData 后保留旧单元格