2011-09-13 30 views
9

Mi sono guardato intorno per trovare una soluzione a questo, ma non riesco a trovarne uno che funzioni per me. Ho una cella personalizzata con un pulsante all'interno. Il mio problema è come posso passare indexPath al metodo di azione?Azione del pulsante UITableViewCell personalizzato?

In questo momento sto facendo

[cell.showRewards addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside]; 

Nel mio metodo cellForRowAtIndexPath e il mio metodo è:

-(IBAction)myAction:(id)sender{ 
NSIndexPath *indexPath = [self.tableView indexPathForCell:(MyCustomCell *)[sender superview]]; 
NSLog(@"Selected row is: %d",indexPath.row); 
} 

Qualche consiglio? Grazie.

+0

Si sta utilizzando il didSelectRow: metodo? – tipycalFlow

risposta

5

Mentre io sento l'impostazione tag per il pulsante è un modo per andare. Potrebbe essere necessario scrivere codice per assicurarsi che ogni volta che la cella viene riutilizzata, il tag appropriato venga aggiornato sull'oggetto button.

Invece ho la sensazione che questo potrebbe funzionare. Prova questo -

-(IBAction)myAction:(id)sender 
{ 
CGPoint location   = [sender locationInView:self.tableView]; 
NSIndexPath *indexPath  = [self.tableView indexPathForRowAtPoint:location]; 
UITableViewCell *swipeCell = [self.tableView cellForRowAtIndexPath:indexPath]; 

NSLog(@"Selected row: %d", indexPath.row); 
//...... 
} 

In sostanza quello che stai facendo è sempre le coordinate del luogo in cui il clic è successo con rispetto al tuo tableView. Dopo aver ottenuto le coordinate, tableView può fornire indexPath utilizzando il metodo indexPathForRowAtPoint:. Sei pronto per andare dopo questo ...

Voilà, non hai solo il indexPath ma anche la cella reale in cui è avvenuto il clic. Per ottenere i dati effettivi dal datasource (supponendo la sua NSArray), si può fare -

[datasource objectAtIndex:[indexPath row]];

+0

Stavo per suggerire NSIndexPath * indexPath = [tableView indexPathForRowAtPoint: [[[evento toccaForView: pulsante] anyObject] locationInView: tableView]]; ma questo è molto più pulito, grazie! – phi

+3

Hmm, mi manca qualcosa qui? In realtà [posizione del mittenteInView: self.tableView]; lavoro per te? – phi

+0

Non per me. Ottengo [UIButton locationInView:]: selettore non riconosciuto inviato a instanc. – djskinner

2

È possibile assegnare indexpath di modifica del tasto e l'accesso nel metodo come

cell.showRewards.tag = indexPath.row; 

-(IBAction)myAction:(id)sender 
{ 
    NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender tag]]; 
    NSLog(@"Selected row is: %d",indexPath.row); 
} 
3

provare questo.

cell.showRewards.tag=indextPath.row 

attuare questo metodo cellForRowAtIndexPath di Tableview.

-(IBAction)myAction:(id)sender{ 
UIButton* btn=(UIButton*)sender; 
NSLog(@"Selected row is: %d",btn.tag); 
} 
3

si imposta il tag tasto value = indexpath e controllare in funzione se il valore di tag è questo fare ciò che u vuole

7
cell.showRewards.tag = indexPath.row; 

-(IBAction)myAction:(id)sender 
{ 
UIButton *btn = (UIButton *)sender; 
int indexrow = btn.tag; 
NSLog(@"Selected row is: %d",indexrow); 
} 
+3

Funziona, uso invece di UIButton posizioneInView – JulianB

2

in costume UITableViewCell classe:

[self.contentView addSubview:but_you]; 

In cellForRowAtIndexPath metodo è possibile scrivere:

[cell.showRewards addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside];  
cell.showRewards.tag = indexPath.row; 
1

In [sender superview] non si accede a MyCustomCell, ma è contentView. Leggi UITableViewCell Classe Riferimento:

contentView Restituisce la vista contenuto dell'oggetto cellulare.(Sola lettura)

@property(nonatomic, readonly, retain) UIView *contentView 

Discussione: La vista contenuto di un oggetto UITableViewCell è la superview predefinita per i contenuti visualizzati dalla cellula. Se si desidera personalizzare le celle aggiungendo semplicemente viste aggiuntive, è necessario aggiungerle alla vista del contenuto in modo che vengano posizionate correttamente quando le transizioni delle celle entrano e escono dalla modalità di modifica.

Il modo più semplice per modificare il codice è utilizzare [[sender superview] superview]. Ma questo smetterà di funzionare se in seguito modifichi la tua cella e inserisci il pulsante in un'altra vista. contentView è apparso in iPhoneOS 2.0. Modifiche future simili influenzeranno il tuo codice. Che il motivo per cui non suggerisco di usare in questo modo.

1

Trovo incredibile che non ci sia davvero una soluzione decente a questo.

Per qualsiasi motivo, trovo che i metodi di codifica e "l'uso della posizione visiva della cella sullo schermo per identificare l'oggetto modello corretto" delineato nell'altra risposta un po 'sporco.

Qui ci sono due diversi approcci al problema:

Subclassing UITableViewCell

La soluzione sono andato con era a lezione sub UITableViewCell

@interface MyCustomCell : UITableViewCell 

@property (nonatomic, strong) Model *myModelObject; 

@end 

Quando si crea la cella in cellForRowAtIndexPath: sei è probabile che utilizzi l'oggetto modello per popolare i dati della cella. In questo metodo è possibile assegnare l'oggetto del modello alla cella.

E poi nel gestore rubinetto tasto:

MatchTile *cell = (MatchTile *) sender.superview.superview; 

if (cell && cell.myModelObject) 
{ 
    //Use cell.myModelObject 
} 

io non sono al 100% soddisfatti di questa soluzione ad essere onesti. Associare un oggetto dominio a un componente UIKit specializzato è una cattiva pratica.

Usa Objective-C associativa Oggetti

Se non si desidera sottoclasse della cellula c'è un altro po 'di inganno è possibile utilizzare per associare l'oggetto del modello con la cella e recuperare in un secondo momento.

Per recuperare l'oggetto modello dalla cella, è necessario disporre di una chiave univoca per identificarlo. Definire uno come questo:

static char* OBJECT_KEY = "uniqueRetrievalKey"; 

Aggiungere la seguente riga al vostro metodo di cellForRowAtIndexPath: quando si utilizza il modello a oggetti per popolare la cella. Questo associerà il tuo oggetto modello all'oggetto cella.

objc_setAssociatedObject(cell, OBJECT_KEY, myModelObject, OBJC_ASSOCIATION_RETAIN); 

E poi ovunque ci sia un riferimento a tale cella è possibile recuperare l'oggetto del modello utilizzando:

MyModelObject *myModelObject = (MyModelObject *) objc_getAssociatedObject(cell, OBJECT_KEY); 

Nella riflessione, anche se ho optato per la prima (perché avevo già sottoclasse della cella), la seconda soluzione è probabilmente un po 'più pulita in quanto rimane responsabilità del ViewController per collegare e recuperare l'oggetto del modello.UITableViewCell non ha bisogno di sapere nulla a riguardo.

8

Voglio solo aggiungere quello che credo sia la migliore soluzione di tutti: una categoria su UIView.

E 'semplice come questo:

- (void)somethingHappened:(id)sender 
{ 
    NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender parentCell]]; 

    // Your code here... 
} 

Basta usare questa categoria su UIView:

@interface UIView (ParentCell) 

- (UITableViewCell *)parentCell; 

@end 

@implementation UIView (ParentCell) 

- (UITableViewCell *)parentCell 
{ 
    UIView *superview = self.superview; 
    while(superview != nil) { 
     if([superview isKindOfClass:[UITableViewCell class]]) 
      return (UITableViewCell *)superview; 

     superview = superview.superview; 
    } 

    return nil; 
} 

@end 
+1

Questa è in realtà una bella categoria e gestisce sia iOS 7 sia manderson

1

In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath metodo di scrivere il codice qui sotto:

[cell.zoomButton addTarget:self action:@selector(navigateAction:) forControlEvents:UIControlEventTouchUpInside]; 
cell.zoomButton.tag=indexPath.row; 

Quindi scrivere un metodo così:

-(IBAction)navigateAction:(id)sender 
{ 
UIButton *btn = (UIButton *)sender; 
int indexrow = btn.tag; 
NSLog(@"Selected row is: %d",indexrow); 

currentBook = [[bookListParser bookListArray] objectAtIndex:indexrow]; 

KitapDetayViewController *kitapDetayViewController; 
if(IS_IPHONE_5) 
{ 
    kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:@"KitapDetayViewController" bundle:Nil]; 
} 

else 
{ 
    kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:@"KitapDetayViewController_iPhone4" bundle:Nil]; 
} 
kitapDetayViewController.detailImageUrl = currentBook.detailImageUrl; 
kitapDetayViewController.bookAuthor = currentBook.bookAuthor; 
kitapDetayViewController.bookName = currentBook.bookName; 
kitapDetayViewController.bookDescription = currentBook.bookDescription; 
kitapDetayViewController.bookNarrator=currentBook.bookNarrator; 
kitapDetayViewController.bookOrderHistory=currentBook.bookOrderDate; 
int byte=[currentBook.bookSizeAtByte intValue]; 
int mb=byte/(1024*1024); 
NSString *mbString = [NSString stringWithFormat:@"%d", mb]; 
kitapDetayViewController.bookSize=mbString; 
kitapDetayViewController.bookOrderPrice=currentBook.priceAsText; 
kitapDetayViewController.bookDuration=currentBook.bookDuration; 
kitapDetayViewController.chapterNameListArray=self.chapterNameListArray; 
// [[bookListParser bookListArray ]release]; 
[self.navigationController pushViewController:kitapDetayViewController animated:YES]; 
} 
1

Se si desidera che il percorso indice del pulsante Detecting which UIButton was pressed in a UITableView descriva come.

fondamentalmente l'azione tasto diventa:

- (void)checkButtonTapped:(id)sender 
    { 
     CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; 
     NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition]; 
     if (indexPath != nil) 
     { 
     ... 
     } 
    } 
0

Ecco il "Modo più semplice" per farlo (Testato su IOS11):

NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint 
[[[sender superview] superview] center]]; 
Problemi correlati