如何刷新 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?