如何使单元格中的 UIButton 在被点击后立即保持特定状态?
Posted
技术标签:
【中文标题】如何使单元格中的 UIButton 在被点击后立即保持特定状态?【英文标题】:How do I make UIButton in a cell retain a specific state right after being tapped? 【发布时间】:2014-04-26 11:50:28 【问题描述】:所以我在UICollectionView
中有一个项目列表,并且有一个UIButton
是默认设置并选择UIImage
设置为浅灰色心形和黑色心形。
我的目标是允许用户将项目添加到收藏夹列表中。我在数据库中添加了一个名为“favourite”的列,它是布尔类型。
客户点击项目单元格中的心脏。触发一个方法,该方法使用作为 UIButton
的 titleLabel 传递的项目的对象 ID 从数据库中获取项目并将收藏列的布尔值更新为“True”。
收藏按钮方法:
- (void)addFavouriteButtonTapped:(UIButton *)sender
NSLog(@"add to favourites button tapped %@", [[sender titleLabel] text]);
// Set data base favaourite status to 1 (yes)
PFQuery *query = [PFQuery queryWithClassName:@"Garments"];
[query getObjectInBackgroundWithId:[[sender titleLabel] text] block:^(PFObject *object, NSError *error)
object[@"favourite"] = @YES;
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
if (!error)
[[[UIAlertView alloc] initWithTitle:@"Add Favouite"
message:@"Item successfully added to favourites"
delegate:_thisController
cancelButtonTitle:@"Ok"
otherButtonTitles: nil] show];
else
NSLog(@"Something went wrong");
];
];
然后在我的cellForItemAtIndexPath
中,我有一个 if 语句来设置UIButton
的选定状态。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
NSLog(@"cellForItemAtIndexPath");
// other cell info here deleted to make things clearer
_addFavouriteButton = [cell addFavouriteButton];
// if database favourites status is equal to one then set highlighted to (yes)
if ([object valueForKey:@"favourite"] == [NSNumber numberWithBool:YES])
[_addFavouriteButton setSelected:YES];
NSLog(@"SETTING SELECTED");
else if ([object valueForKey:@"favourite"] == [NSNumber numberWithBool:NO])
[_addFavouriteButton setSelected:NO];
[[_addFavouriteButton titleLabel] setText:[object objectId]];
[_addFavouriteButton addTarget:_thisController action:@selector(addFavouriteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
return cell;
现在,当我离开视图并且一切都被破坏然后再次返回时,黑色的心出现在我选择最喜欢的地方。这可以。我遇到的问题是,当我实际选择要添加为收藏的项目时,心脏会更新并保持灰色,直到我离开 UICollectionView
并返回。
我在 addFavouriteButtonTapped: 方法的主队列中尝试了reloadData
我也试过只重新加载单元格。
这些都不起作用。
我可以将UIButton
的状态设置为选中,但是当我滚动时,选择不会保持位置并移动到其他单元格UIButton
并使用我实际选择的按钮离开单元格。解决这个问题的唯一方法是保留少数几个,这样我们就有了一个新的UICollectionView
,它使用我数据库中的 if 语句来确定是否选择了一个单元格。
**My custom cell:**
@interface VAGGarmentCell : UICollectionViewCell
@property (weak, nonatomic) IBOutlet PFImageView *imageView;
@property (weak, nonatomic) IBOutlet UIButton *addFavouriteButton;
@property (weak, nonatomic) IBOutlet UITextView *title;
@property (weak, nonatomic) IBOutlet UILabel *price;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
@end
问题:
我已经完成了大部分需要完成的工作,以后可以在构建列出客户收藏列表中的项目的页面时使用收藏列。但是如何在点击按钮并成功更新后立即刷新UICollectionView
以显示UIButton
的选定状态?
【问题讨论】:
在您的单元格中设置索引路径 _addFavouriteButton.tag=indexpath.row 处的行 【参考方案1】:确保您还将sender
(即按下的按钮)也设置为选中,或者在更新模型后重新加载集合视图。
更新:此答案已在聊天讨论后进行编辑和更新。
在您的视图控制器中,_addFavouriteButton
不需要 iVar
(或 @property
),按钮变量应该只是 collectionView:cellForItemAtIndexPath:object:
方法范围内的局部变量 - 让我们开始吧通过首先修复该方法
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
NSLog(@"cellForItemAtIndexPath");
// other cell info here deleted to make things clearer
// Create a local variable for your button - this saves a bit of typing in the rest
// of the method. You can also use dot notation as its a property
UIButton *favouriteButton = cell.addFavouriteButton;
BOOL objectFavourited = [object[@"favourite"] boolValue];
NSLog(@"Setting selected? %@", objectFavourited ? @"YES" : @"NO");
favouriteButton.selected = objectFavourited;
// You should set the title directly on the button (as per the docs -
// https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIButton_Class/UIButton/UIButton.html#//apple_ref/occ/instp/UIButton/titleLabel),
// you shouldn't touch titleLabel except for styling
// However you only used the title for seeing which object the favourite button tap was for,
// so I've commented it out
// [favouriteButton setTitle:[object objectId] forState:UIControlStateNormal];
[favouriteButton addTarget:_thisController action:@selector(addFavouriteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
return cell;
现在是按钮目标方法。在这里您应该执行以下操作:更新您的模型,更改按钮状态,然后保存模型。如果模型成功保存,您的用户是否关心 - 不是真的!但是,如果保存失败,则用户需要知道,并且按钮和模型需要恢复到之前的状态。
我很确定如果保存失败,对象将处于与您尝试保存之前相同的状态——favourite
属性设置为YES
。即使没有,将其设置回NO
也无所谓。
获得按下按钮的项目的indexPath
的最佳方法是使用与this answer 中的方法类似的方法。它是计算索引路径的完美方式,不需要可怕的标签!
现在我们有了项目的索引路径,你不需要查询那个特定的对象——我们直接使用objectAtIndexPath:
得到它。
- (void)addFavouriteButtonTapped:(UIButton *)button
// Method adapted for a collection view from the above answer
CGPoint hitPoint = [button convertPoint:CGPointZero toView:self.collectionView];
NSIndexPath *hitIndex = [self.collectionView indexPathForItemAtPoint:hitPoint];
// Now get the object for this index
PFObject *object = [self objectAtIndexPath:hitIndex];
NSLog(@"add to favourites button tapped %ld - %@", (long)hitIndex.item, [object objectId]);
// Now update the model
object[@"favourite"] = @YES;
// And the button state
button.selected = YES;
// Now save the model to parse
[object saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
if (!succeeded)
// Reset the object back to its previous state
object[@"favourite"] = @NO;
// Reload the item to reflect the changes in the model
[self.collectionView reloadItemsAtIndexPaths:@[hitIndex]];
// Only bother the user if something bad happened
[[[UIAlertView alloc] initWithTitle:@"Oops!"
message:@"There was a problem please try again later"
delegate:self
cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil] show];
];
您可以重新加载集合视图,但由于您已使用该方法更新了视图,因此实际上没有任何必要。 但是,如果保存失败,您应该重新加载集合视图,因为该按钮现在可能正在用于集合视图中的其他项目!
【讨论】:
这是我尝试的第一件事,但是当我滚动然后返回单元格时,我选择了它上面的按钮不再被选中。 问题是在查询完成之前你没有做任何UI明智的事情,所以在请求完成之前不会选择你的按钮。实际上,我会在我的回答中注明:) 那么在 _addFavoute 方法的顶部添加 hitPoint 代码?然后在索引路径成功更新重新加载项目后?我已经用你的代码试过了,它对我不起作用。 由于某种原因,重新加载似乎不起作用。我什至试过 [_collectionView reloadItemsAtIndexPaths:[_collectionView indexPathsForVisibleItems]]; @LondonGuy 是的,在addFavouriteButtonTapped:
方法的顶部。实际上你可以发布更多代码,比如object
是什么?它应该是一个数组,但它似乎不是?以上是关于如何使单元格中的 UIButton 在被点击后立即保持特定状态?的主要内容,如果未能解决你的问题,请参考以下文章
如何使自定义单元格中的 UILabel 显示保存在 UITableView 中的更改
如何从模态 UIView 更新自定义单元格中的 UIButton 标题