储蓄,保留,和检索数组

时间:2016-08-11 02:16:18

标签: ios objective-c arrays uitableview nsuserdefaults

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

我有一个包含本地JSON文件数据的tableview。我需要用户能够:

  1. 选择多个单元格
  2. 在所选单元格上显示复选标记
  3. 将这些选择写入数组
  4. 取消选中时删除选择
  5. 5。当用户切换视图或离开并返回到tableview,关闭并重新打开应用程序等时,使用复选标记保存/保留选择

    我已经设法让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代码。 / p>

    我如何编码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])
    
    }
    

2 个答案:

答案 0 :(得分:0)

您的解决方案非常简单。

  1. 首先,您需要将一系列选定的索引路径保存到用户默认对象,而不是仅保留最后选择的路径。
  2. 每当用户选择或取消选择一行时。添加和删​​除同一阵列中的对象并将其保存回用户默认值。
  3. ComponentDidMount中,检查您的索引路径是否存在于用户默认值中保存的阵列中。如果存在,请选中带有复选标记的行,否则保持原样。
  4. 希望这会有所帮助。

答案 1 :(得分:0)

我认为不是使用那些indexPath,而是建议您直接使用数据本身,添加Bool属性以指示Ingredient类中的选择,然后保存CoreData/Realm/NSUserDefault中的整个数组,由于您的数据可以更改,导致您保存的选择indexPath不再正确,因此更正确