Usando una image personalizada para un accesorio Access de UITableViewCell y haciéndolo responder a UITableViewDelegate

Estoy usando un UITableViewCell dibujado personalizado, incluido el mismo accessoryView la celda AccessView. Mi configuration para el accesorioView ocurre a propósito de algo como esto:

 UIImage *accessoryImage = [UIImage imageNamed:@"accessoryDisclosure.png"]; UIImageView *accImageView = [[UIImageView alloc] initWithImage:accessoryImage]; accImageView.userInteractionEnabled = YES; [accImageView setFrame:CGRectMake(0, 0, 28.0, 28.0)]; self.accessoryView = accImageView; [accImageView release]; 

También cuando la celda se inicializa, usando initWithFrame:reuseIdentifier: me initWithFrame:reuseIdentifier: de establecer la siguiente propiedad:

 self.userInteractionEnabled = YES; 

Desafortunadamente en mi UITableViewDelegate, mi tableView:accessoryButtonTappedForRowWithIndexPath: método (intenta repetir eso 10 veces) no se activa. El delegado definitivamente está conectado correctamente.

¿Qué es posible que falte?

Gracias a todos.

Lamentablemente, ese método no recibe una llamada a less que se toca el tipo de button interno proporcionado cuando usa uno de los types pnetworkingefinidos. Para usar el tuyo, tendrás que crear tu accesorio como un button u otra subclass de UIControl (recomiendo un button usando -buttonWithType:UIButtonTypeCustom y configurando la image del button, en lugar de usar un UIImageView).

Aquí hay algunas cosas que uso en Outpost, que personaliza lo suficiente de los widgets estándar (un poco, para que coincida con nuestro colorante verde azulado) que terminé haciendo mi propia subclass intermediaria UITableViewController para mantener el código de utilidad para todas las demás vistas de tabla para usar (ahora subclass OPTableViewController).

En primer lugar, esta function devuelve un nuevo button de divulgación de detalles utilizando nuestro gráfico personalizado:

 - (UIButton *) makeDetailDisclosureButton { UIButton * button = [UIButton outpostDetailDisclosureButton]; [button addTarget: self action: @selector(accessoryButtonTapped:withEvent:) forControlEvents: UIControlEventTouchUpInside]; return ( button ); } 

El button llamará a esta rutina cuando finalice, que luego alimenta la rutina estándar UITableViewDelegate para los botones de accesorios:

 - (void) accessoryButtonTapped: (UIControl *) button withEvent: (UIEvent *) event { NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint: [[[event touchesForView: button] anyObject] locationInView: self.tableView]]; if ( indexPath == nil ) return; [self.tableView.delegate tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath]; } 

Esta function ubica la fila al get la location en la vista de tabla de un toque del evento proporcionado por el button y preguntando a la vista de la tabla la ruta de índice de la fila en ese punto.

Encontré este website para ser muy útil: vista de accesorios personalizados para tu uitableview en iPhone

En resumen, use esto en cellForRowAtIndexPath: ::

 UIImage *image = (checked) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height); button.frame = frame; [button setBackgroundImage:image forState:UIControlStateNormal]; [button addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside]; button.backgroundColor = [UIColor clearColor]; cell.accessoryView = button; 

luego, implementa este método:

 - (void)checkButtonTapped:(id)sender event:(id)event { NSSet *touches = [event allTouches]; UITouch *touch = [touches anyObject]; CGPoint currentTouchPosition = [touch locationInView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition]; if (indexPath != nil) { [self tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath]; } } 

Mi enfoque es crear una subclass UITableViewCell y encapsular la lógica que llamará al UITableViewDelegate habitual de UITableViewDelegate .

 // CustomTableViewCell.h @interface CustomTableViewCell : UITableViewCell - (id)initForIdentifier:(NSString *)reuseIdentifier; @end // CustomTableViewCell.m @implementation CustomTableViewCell - (id)initForIdentifier:(NSString *)reuseIdentifier; { // the subclass specifies style itself self = [super initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier]; if (self) { // get the button elsewhere UIButton *accBtn = [ViewFactory createTableViewCellDisclosureButton]; [accBtn addTarget: self action: @selector(accessoryButtonTapped:withEvent:) forControlEvents: UIControlEventTouchUpInside]; self.accessoryView = accBtn; } return self; } #pragma mark - private - (void)accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event { UITableViewCell *cell = (UITableViewCell*)button.superview; UITableView *tableView = (UITableView*)cell.superview; NSIndexPath *indexPath = [tableView indexPathForCell:cell]; [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } @end 

Una extensión de la respuesta de Jim Dovey anterior:

Tenga cuidado cuando use un UISearchBarController con su UITableView. En ese caso, desea verificar self.searchDisplayController.active y utilizar self.searchDisplayController.searchResultsTableView lugar de self.tableView . De lo contrario, obtendrá resultados inesperados cuando searchDisplayController esté activo, especialmente cuando los resultados de búsqueda se desplacen.

Por ejemplo:

 - (void) accessoryButtonTapped:(UIControl *)button withEvent:(UIEvent *)event { UITableView* tableView = self.tableView; if(self.searchDisplayController.active) tableView = self.searchDisplayController.searchResultsTableView; NSIndexPath * indexPath = [tableView indexPathForRowAtPoint:[[[event touchesForView:button] anyObject] locationInView:tableView]]; if(indexPath) [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } 
  1. Definir una macro para tags de botones:

     #define AccessoryViewTagSinceValue 100000 // (AccessoryViewTagSinceValue * sections + rows) must be LE NSIntegerMax 
  2. Cree el button y configure cell.accessoryView al crear una celda

     UIButton *accessoryButton = [UIButton buttonWithType:UIButtonTypeContactAdd]; accessoryButton.frame = CGRectMake(0, 0, 30, 30); [accessoryButton addTarget:self action:@selector(accessoryButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; cell.accessoryView = accessoryButton; 
  3. Establezca cell.accessoryView.tag mediante indexPath en el método UITableViewDataSource -tableView: cellForRowAtIndexPath:

     cell.accessoryView.tag = indexPath.section * AccessoryViewTagSinceValue + indexPath.row; 
  4. Manejador de events para botones

     - (void) accessoryButtonTapped:(UIButton *)button { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:button.tag % AccessoryViewTagSinceValue inSection:button.tag / AccessoryViewTagSinceValue]; [self.tableView.delegate tableView:self.tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } 
  5. Implementar el método UITableViewDelegate

     - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { // do sth. } 

Cuando se toca el button, puede hacer que llame al siguiente método dentro de una subclass UITableViewCell

  -(void)buttonTapped{ // perform an UI updates for cell // grab the table view and notify it using the delegate UITableView *tableView = (UITableView *)self.superview; [tableView.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:[tableView indexPathForCell:self]]; } 

Con el enfoque yanchenko tuve que agregar: [accBtn setFrame:CGRectMake(0, 0, 20, 20)];

Si está utilizando el file xib para personalizar su tablaCell, entonces initWithStyle: reuseIdentifier: no se llamará.

En lugar de anular:

 -(void)awakeFromNib { //Put your code here [super awakeFromNib]; } 

Debe utilizar un UIControl para get correctamente el envío de events (por ejemplo, un UIButton ) en lugar de UIView/UIImageView simple.

A partir de iOS 3.2, puede evitar los botones que otros recomiendan aquí y, en su lugar, usar su UIImageView con un reconocimiento de gestos táctil. Asegúrese de habilitar la interacción del usuario, que está desactivada de forma pnetworkingeterminada en UIImageViews.