Как получить доступ из UICollectionViewCell indexPath ячейки в UICollectionView
Я хочу оживить UICollectionViewCell
при вызове действия.
я сделал UICollectionViewCell
в Interface Builder
, UICollectionView
.
Теперь я хочу получить правильный indexPath
по моему методу actionBtnAddToCard
.
Вот как я это делаю сейчас (метод в ProduktViewCell.m):
- (IBAction)actionAddToCart:(id)sender {
XLog(@"");
// see this line
NSIndexPath *indexPath = ??** how can i access the correct indexPath**??;
SortimentViewController *svc = [[SortimentViewController alloc] initWithNibName:@"SortimentViewController_iPad" bundle:[NSBundle mainBundle]];
[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
[svc collectionView:svc.collectionViewProdukte didSelectItemAtIndexPath:indexPath];
}
SortimentViewController - это viewController, который наследует UICollectionView.
как получить правильный indexPath?
ОБНОВЛЕНИЕ 1: отредактированный пост для лучшего понимания.
Ответы
Ответ 1
если вы знаете иерархию представления, это легко.
UIButton *button = (UiButton *) sender;
если кнопка похожа на эту кнопку → UITableViewCell →
тогда вы можете получить ячейку следующим образом
UITableViewCell *cell = (UITableViewCell *)[button superview];
если кнопка похожа на эту кнопку → UITableViewCell → вид содержимого →
UITableViewCell *cell = (UITableViewCell *)[[button superview] superview];
и, наконец, путь индекса можно извлечь следующим образом:
NSIndexPath *indexPath = [self.table_View indexPathForCell:cell];
Ответ 2
- (IBAction)actionAddToCart:(id)sender {
NSIndexPath *indexPath;
indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]];
...
}
Ответ 3
Использование кода типа [[button superview] superview]
является хрупким, а не перспективным; действительно, он даже не гарантированно работает на всех версиях iOS, если вы явно не протестируете его. Для этой цели я всегда использую итеративный вспомогательный метод: -
- (UIView *)superviewWithClassName:(NSString *)className fromView:(UIView *)view
{
while (view)
{
if ([NSStringFromClass([view class]) isEqualToString:className])
{
return view;
}
view = view.superview;
}
return nil;
}
Затем я вызываю его из обработчика кнопки следующим образом: -
- (IBAction)buttonClicked:(id)sender
{
UIButton *button = (UIButton *)sender;
UICollectionViewCell *cell = (UICollectionViewCell *)
[self superviewWithClassName:@"UICollectionViewCell"
fromView:button];
if (cell)
{
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
// do whatever action you need with the indexPath...
}
}
UPDATE: Быстрая версия superviewWithClassName
. Сделал его методом класса, так как он никогда не ссылается на self
.
static func superviewWithClassName(className:String, fromView view:UIView?) -> UIView? {
guard let classType = NSClassFromString(className) else {
return nil
}
var v:UIView? = view
while (v != nil) {
if v!.isKindOfClass(classType) {
return v
}
v = v!.superview
}
return nil
}
и некоторый код для вызова, либо из prepareForSegue
, либо с помощью обработчика кнопок: -
guard let cell = UIView.superviewWithClassName("UICollectionViewCell", fromView: sender as? UIView) as? UITableViewCell else {return}
Ответ 4
Не зависит от вида.
Попробуйте это.
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:buttonPosition];
NSLog(@"%ld", (long)indexPath.row);
Ответ 5
Если вы хотите анимировать определенную ячейку, вам нужно получить ссылку на эту ячейку. Просто позвонив
[svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
ничего не делает. Вам нужно сохранить ячейку, возвращаемую методом, например:
UICollectionViewCell *cell = [svc.collectionViewProdukte cellForItemAtIndexPath:indexPath];
После этого перейдите и анимируйте:
[UIView animateWithDuration:0.2f animations:^{
cell.transform = CGAffineTransformMakeScale(0.5f, 0.5f);
}];
Ответ 6
Вы можете сделать это так, indexPathsForVisibleItems вернет массив NSIndexPaths для элементов, которые теперь видны в представлении, а первый объект возвращает первый (если у вас есть одна ячейка для каждого представления).
NSIndexPath *indexPath = [[svc.collectionViewProdukte indexPathsForVisibleItems] firstObject]
Ответ 7
Быстрое решение:
Для этого может быть полезно расширение UICollectionView, подобное этому.
extension UICollectionView {
func indexPathForView(view: AnyObject) -> NSIndexPath? {
let originInCollectioView = self.convertPoint(CGPointZero, fromView: (view as! UIView))
return self.indexPathForItemAtPoint(originInCollectioView)
}
}
Использование становится легко повсеместно.
let indexPath = collectionView.indexPathForView(button)
Ответ 8
Swift 3 Решение: на основе ответа Ишана Ханды
extension UICollectionView {
func indexPathForView(view: AnyObject) -> IndexPath? {
let originInCollectioView = self.convert(CGPoint.zero, from: (view as! UIView))
return self.indexPathForItem(at: originInCollectioView) as IndexPath?
}
}
Использование:
func deleteCell(sender:UIButton){
var indexPath:IndexPath? = nil
indexPath = self.collectionView.indexPathForView(view: sender)
print("index path : \(indexPath)")
}
Ответ 9
//Note: this is for a storyboard implementation
// here is code for finding the row and section of a textfield being edited in a uicollectionview
UIView *contentView = (UIView *)[textField superview];
UICollectionViewCell *cell = (UICollectionViewCell *)[contentView superview];
cell = (UICollectionViewCell *)[contentView superview];
// determine indexpath for a specific cell in a uicollectionview
NSIndexPath *editPath = [myCollectionView indexPathForCell:cell];
int rowIndex = editPath.row;
int secIndex = editPath.section;
Ответ 10
Несмотря на то, что многие ответы, которые я нашел здесь, будут самыми короткими и полезными независимо от иерархии представлений.
- (void) actionAddToCart:(id)sender
{
id view = [sender superview];
while (view && [view isKindOfClass:[UICollectionViewCell class]] == NO)
{
view = [view superview];
}
NSIndexPath *thisIndexPath = [self.collectionView indexPathForCell:view];
NSLog(@"%d actionAddToCart pressed",thisIndexPath.row);
}
Ответ 11
У вас почти наверняка есть подкласс UICollectionViewCell. Просто добавьте свойство и установите indexPath в cellForItemAtIndexPath.