如何刷新 UICollectionView 以反映对我的数据源所做的最新更改?

Posted

技术标签:

【中文标题】如何刷新 UICollectionView 以反映对我的数据源所做的最新更改?【英文标题】:How do I refresh a UICollectionView so it reflects the most recent changes made to my dataSource? 【发布时间】:2014-04-29 11:55:32 【问题描述】:

我正在应用中实现过滤器的功能,该过滤器使用商品的价格对商品进行排序。我想让客户能够使用 UIPickerView 按价格从高到低或从低到高对商品进行排序。

外观的想法:

问题:

我遇到的问题是在我查询了 parse.com 数据库并获得了新排序的数据之后,为我的 UICollectionView 重新加载数据没有任何效果。我觉得这很令人困惑,因为我正在更改我的实际数据源(存储数据库结果的 NSArray)。所以我在重新加载数据时收集了我的UICollectionView 将获取最新结果。但是什么也没发生。

我的设置如下:

跟踪 UIPickerView(过滤器)是否被激活:

@implementation VAGGarmentsCollectionViewController

    BOOL _filterActivated;

当点击过滤器打开 UIPickerView 时,将 _filterActivated 实例变量设置为 yes:

- (void)filterButtonTapped
    
    // I have all code in here to create the UIPickerView
    // Deleted it all to make the post clearer    

    _filterActivated = YES;

设置 UIPickerView 行的标题:

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component

    return [_filterPickerArray objectAtIndex:row];


- (void)loadTitleForIndex:(NSInteger)index

    if (index == 0) 
        [_filterButton setTitle:@"Recommend" forState:UIControlStateNormal];
     else if (index == 1) 
        [_filterButton setTitle:@"What's New" forState:UIControlStateNormal];
     else if (index == 2) 
        [_filterButton setTitle:@"High to Low" forState:UIControlStateNormal];
     else if (index == 3) 
        [_filterButton setTitle:@"Low to High" forState:UIControlStateNormal];
    

检测 UIPickerView 中特定行的选择:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

    NSIndexPath *selectedObjectIndex = [_filterPickerArray objectAtIndex:row];
    NSInteger indexOfSelectedObject = [_filterPickerArray indexOfObject:selectedObjectIndex];

    //Let's print in the console what the user had chosen;
    NSLog(@"Chosen item: %@", [_filterPickerArray objectAtIndex:row]);

    [_thisController loadTitleForIndex:indexOfSelectedObject];

    _selectedRowInFilterPicker = [_filterPicker selectedRowInComponent:0];

检测何时点击完成按钮:

- (void)pickerDoneButtonTapped

    NSLog(@"Picker done button pressed");

    [_thisController performQuery];
    [_collectionView reloadData];

    _filterActivated = NO;

然后我有一个 performQuery 方法,它调用 queryForCollection 方法以在从 parse.com 在后台抓取数据之前采用任何其他查询选项

采集方式查询:

-(PFQuery *)queryForCollection

    PFQuery *query = [PFQuery queryWithClassName:@"Garments"];
    if (_filterActivated) 
        // check what the selectedRowInFilterPicker currently is
        // then add that task to the query
        NSLog(@"FILTER WAS ACTIVATED");

        if (_selectedRowInFilterPicker == 0) 

         else if (_selectedRowInFilterPicker == 1) 

         else if (_selectedRowInFilterPicker == 2) 
            NSLog(@"ORDER BY DESCENDING USING PRICE");
            [query orderByDescending:@"price"];
         else if (_selectedRowInFilterPicker == 3) 
            NSLog(@"ORDER BY ASCENDING USING PRICE");
            [query orderByAscending:@"price"];
        
    
    return query;

执行查询方法:

- (void)performQuery

    NSLog(@"PERFORM QUERY");
    PFQuery *query = self.queryForCollection;

    if (_paginationEnabled) 
        [query setLimit:_objectsPerPage];
        //fetching the next page of objects
        if (!_isRefreshing) 
            [query setSkip:self.objects.count];
        
    


    [self objectsWillLoad];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) 


        self.isLoading = NO;
        if (error)
            self.objects = [NSArray new];
        else 
            if (_paginationEnabled && !_isRefreshing) 
                //add a new page of objects
                NSMutableArray *mutableObjects = [NSMutableArray arrayWithArray:self.objects];
                [mutableObjects addObjectsFromArray:objects];
                self.objects = [NSArray arrayWithArray:mutableObjects];
            
            else 
                self.objects = objects;
            
        


        [self objectsDidLoad:error];
    ];

分解一下我在做什么:

检测 UIPickerView 已使用“filterButtonTapped”方法将“_filterActivated”实例变量设置为 yes。

点击完成按钮时执行查询。 performQuery 方法调用 queryForCollection 方法。在该方法中,我检查“_filterActivated”是否设置为yes,如果是,然后检查UIPickerView 中的哪一行被选中,并将适当的查询选项添加到查询中。

然后,我希望在 performQuery 方法完成后重新加载我的 UICollectionView 的数据。没发生什么事。我也尝试过重新加载可见项目和索引路径中的项目,但仍然一无所获。

也许我做错了。我睡在上面,想今天下午再试试,但还是看不出哪里出错了。

我想做的事:

我想要做的就是在UIPickerView 中选择一个过滤器选项/行(例如,从低到高排序的项目)并点击@ 的完成UIButton 之后重新加载整个UICollectionView 987654337@.

更新:

- (void)objectsDidLoad:(NSError *)error

    _lastLoadedData = [NSDate date];
    [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.collectionView];
    [_loadingIndicator stopAnimating];
    [self.collectionView reloadData];


【问题讨论】:

你是在成功回调中调用reloadData吗? 不,在检测我的完成按钮何时被点击的方法中调用它。 【参考方案1】:

您在请求新数据之后,但在实际接收到新数据之前调用 reloadData。

在 performQuery 返回并且在 pickerDoneButtonTapped 中调用 reloadData 之后,正在调用您传递给 findObjectsInBackgroundWithBlock 的块。

reloadData 放在你传递findObjectsInBackgroundWithBlock 的块的末尾,或者放在objectsDidLoad: 方法中。

【讨论】:

刚刚检查了我的 objectsDidLoad 方法,我已经在那里重新加载数据。 是的,刚刚添加到帖子中。 我看到我的代码现在在做什么。我删除了 _filterActivated 因为它不是必需的。推荐项目将默认显示。无论如何,当我在选择器中进行选择后点击完成按钮时,只会附加更多项目(以正确的排序顺序)但在已经存在的项目下方。这对于分页来说是可以的,但当我单击完成按钮时就不行了。当我这样做时,我需要刷新整个页面。 performQuery 的设置方式使这变得复杂。就好像它检测到正在使用分页一样,它在添加更多项目时会跳过一些项目,因此不会再次添加相同的项目。

以上是关于如何刷新 UICollectionView 以反映对我的数据源所做的最新更改?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 RxDataSource 中将新部分反映到 UICollectionView?

npm start:手动刷新浏览器以反映更改

如何在 UICollectionView 下隐藏刷新控件

如何在 UICollectionView 的补充视图中触发刷新

Flutter web 需要刷新浏览器以反映热重启后的变化

如何仅刷新/重绘 uicollectionview 中的补充视图?