¿Cómo usar UITableView dentro de UIScrollView y recibir un clic de celda?

Tengo DiscountListTableViewController que se muestra como una pantalla separada en mi aplicación. Pero hay otra pantalla ( PlaceDetailsViewController ) donde necesito mostrar descuentos relacionados en la parte inferior.

Actualmente, PlaceDetailsViewController.view tiene UIScrollView como contenedor y estoy agregando DiscountListTableViewController.tableView al contenedor UIScrollView.content en viewDidLoad de PlaceDetailsViewController . Esto funciona y la vista de tabla se muestra correctamente, pero no puede recibir clics de celda.

Sé que UITableView hereda de UIScrollView y de alguna manera no se recomienda (pero no está restringido). Sin embargo, desde un punto de vista de acoplamiento flexible, cada componente debe diseñarse de forma que se pueda usar de forma independiente en cualquier otro lugar, y es DiscountListTableViewController en mi caso.

PlaceDetailsViewController componente PlaceDetailsViewController solo necesita DiscountListTableViewController tal como está, por lo que no existe una razón lógica por la que no se pueda usar directamente. ¿Alguna sugerencia?

Respuesta: No hagas esto.

UITableview se hereda de —-> UIScrollView : UIView : UIResponder : NSObject

Apple dice:

Importante: no debe incrustar objetos UIWebView o UITableView en objetos UIScrollView. Si lo hace, puede producirse un comportamiento inesperado porque los eventos táctiles de los dos objetos pueden mezclarse y manejarse de forma incorrecta.

No aconsejado? De alguna manera se sintió como “no hacer” después de leer esto. La imprevisibilidad nunca es un buen comportamiento para la aplicación

Importante: no debe incrustar objetos UIWebView o UITableView en objetos UIScrollView. Si lo hace, puede producirse un comportamiento inesperado porque los eventos táctiles de los dos objetos pueden mezclarse y manejarse de forma incorrecta.

Compartirá cómo resuelto eso. ¿Subclassed UIScrollView y utilizado como contenedor de vista en PlaceDetailsViewController:

 @interface PlaceDetailsContainerUIScrollView : UIScrollView @end @implementation PlaceDetailsContainerUIScrollView - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *result = [super hitTest:point withEvent:event]; if ([result isKindOfClass:[UIView class]] && (result.tag == kDiscountListTableViewCellTag) { UITableView *tableView = (UITableView *) [[result.superview superview] superview]; return tableView; } return result; } @end 

Además, no olvide establecer PlaceDetailsContainerUIScrollView.delaysContentTouches = YES y PlaceDetailsContainerUIScrollView.canCancelContentTouches = NO.

Además, se necesita una pequeña corrección en el método DiscountListTableViewController:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { DiscountDetailsViewController *discountDetailsVC = [[DiscountDetailsViewController alloc] init]; //[self.navigationController pushViewController:discountDetailsVC animated:YES]; // self.navigationController is nill because it's not pushed on nav stack, so will grab the current one: AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; [appDelegate.navigationController pushViewController:discountDetailsVC animated:YES]; }