UICollectionView 总是在当前之前显示上一个选择

Posted

技术标签:

【中文标题】UICollectionView 总是在当前之前显示上一个选择【英文标题】:UICollectionView Always Shows Previous Selection Before Current 【发布时间】:2014-01-30 03:38:57 【问题描述】:

我似乎遇到了一整天都在努力解决的问题。我有一个 UICollectionView。在此视图中,显示了来自核心数据的项目(图像)。您单击图像,它会进入详细视图,其中包含通过相机拍摄图像时输入的更多信息。图像在集合视图中显示良好。我遇到的问题是,总是在显示当前选择之前,首先显示最后一个选择。我不知道该怎么办,这是代码和一些输出。


NSInteger selectedFavoriteIndex;



- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) 
    // Custom initialization

return self;


- (void)viewDidLoad

[super viewDidLoad];
// Do any additional setup after loading the view.



- (void)didReceiveMemoryWarning

[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.

- (NSManagedObjectContext *)managedObjectContext

NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication]delegate];
if ([delegate performSelector:@selector(managedObjectContext)]) 
    context = [delegate managedObjectContext];

return context;



- (void)viewDidAppear:(BOOL)animated
[super viewDidAppear:animated];


//Fetch all the stuff from data store.
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];

NSFetchRequest *fetchRequest =[[NSFetchRequest alloc]initWithEntityName:@"Favorites"];
self.favorites = [[managedObjectContext executeFetchRequest:fetchRequest error:nil]mutableCopy];
[self.collectionView reloadData];
[self.collectionViewLayout invalidateLayout];






-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

    return 1;


-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:    (NSInteger)section

return [self.favorites count];


-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath

static NSString *CellIdentifier = @"Cell";
CustomCollectionCell *customCell = [self.collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];

NSManagedObject *favorite = [self.favorites objectAtIndex:indexPath.row];
[customCell.collectionImageView setImage:[UIImage imageWithData:[favorite valueForKey:@"image"]]];
return customCell;




 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

selectedFavoriteIndex = indexPath.item;
NSLog(@"Index path: %@", indexPath);
NSLog(@"Selected Favorite Index: %ld", (long)selectedFavoriteIndex);
NSLog(@"IndexPath.row: %ld", (long)indexPath.row);
NSLog(@"IndexPath.item: %ld", (long)indexPath.item);


  



-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath




-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender


if ([[segue identifier]isEqualToString:@"moment"]) 
    NSManagedObject *selectedFavorite = [self.favorites objectAtIndex:selectedFavoriteIndex];
    ViewMomentViewController *viewMomentViewController = segue.destinationViewController;
    viewMomentViewController.favorite = selectedFavorite;
    viewMomentViewController.hidesBottomBarWhenPushed = YES;







在此处粘贴时,格式有点混乱。不过,Xcode 中的格式是正确的。这是一些输出。

索引路径:length = 2, path = 0 - 1

我也很困惑为什么路径总是减去,无论是 0-0 还是 0-2。谁能给我解释一下?

【问题讨论】:

0-2 表示第 0 部分,第 2 项 【参考方案1】:

听起来prepareForSeguedidSelectItemAtIndexPath 之前被调用。所以prepareForSegue 会从上一次调用didSelectItemAtIndexPath 中看到selectedFavoriteIndex 的值。

这很容易确认,只需在两种方法中放置NSLog 语句即可查看日志消息在控制台中出现的顺序。

有几种方法可以解决这个问题:

    不要使用故事板定义的转场,而是在didDeselectItemAtIndexPath 之后使用[self.storyboard instantiateViewControllerWithIdentifier:]设置selectedFavoriteIndex进行程序化转场。

    不要依赖didSelectItemAtIndexPath 来设置选定的索引,而是通过调用[self.collectionView indexPathForCell:sender] 来确定@​​987654331@ 中的选定索引(当您使用来自集合视图单元格的故事板segue 时,@987654333 的值@ in prepareForSegue 将是单元格本身,您可以使用它来确定索引路径)。

方法 (2) 如下所示:

NSIndexPath *indexPath = [self.collectionView indexPathForCell:sender];
NSManagedObject *selectedFavorite = [self.favorites objectAtIndex:indexPath.item];

【讨论】:

感谢您的快速回复。 prepareForSegue 确实首先被调用。所以我把你的两个例子都搞砸了,我仍然很困惑。我将prepareForSegue 更改为if ([[segue identifier]isEqualToString:@"moment"]) NSManagedObject *selectedFavorite = [self.favorites objectAtIndex:[self.collectionView indexPathForCell:sender]]; ViewMomentViewController *viewMomentViewController = segue.destinationViewController; viewMomentViewController.favorite = selectedFavorite; viewMomentViewController.hidesBottomBarWhenPushed = YES; 并得到一个错误。 以及我搞砸了didSelectItemAtIndexPath 并且我没有收到任何错误,只是一个空白的下一个视图,可能是因为我没有创建一个对象来提供下一个视图。这是代码selectedFavoriteIndex = indexPath.item; [self.storyboard instantiateViewControllerWithIdentifier:@"moment"]; 这一行是错误的:[self.favorites objectAtIndex:[self.collectionView indexPathForCell:sender]]; 它甚至不应该编译。 objectAtIndex 取一个整数,但你试图给它一个 NSIndexPath。我在回答中添加了更多细节。 是的!非常感谢你的帮助。你添加的最后一行让我更清楚我没有做什么。现在我明白了。

以上是关于UICollectionView 总是在当前之前显示上一个选择的主要内容,如果未能解决你的问题,请参考以下文章

预加载下一个(当前不可见)单元格 UICollectionView

UICollectionView 的单元格在滚动后并不总是刷新

UICollectionView 总是自动调整单元格大小。不使用委托返回的尺寸

识别用户何时触碰 UICollectionView 单元格

在实例化单元格之前调用 UICollectionView 委托方法?

UICollectionView:如何在加载视图之前和之后处理更新?