ios objective-c uitableview uipopovercontroller ios8.1

Retraso impredecible antes de que aparezca UIPopoverController en iOS 8.1



objective-c uitableview (3)

Encontré que deseleccionar la fila antes de intentar mostrar la ventana emergente parece solucionar el problema. Esto puede ser una solución de trabajo útil, pero todavía estoy buscando una mejor respuesta, ya que esto puede no ser robusto.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; // adding this line appears to fix the problem [self showPopover:[tableView cellForRowAtIndexPath:indexPath]]; }

Tenga en cuenta, como comentó Yasir Ali, que para que esta solución funcione, deseleccionar la animación debe estar desactivada. Casi 4 años después de la publicación original, este comportamiento aún afecta a iOS 12, y el informe de errores con Apple todavía está abierto: suspiro.

Este problema ocurre con el SDK 8.1, cuando se ejecuta bajo iOS 8.1, pero no cuando se ejecuta bajo iOS 7. Es solo para iPad. El problema aparece tanto con el simulador como en un dispositivo de hardware.

El siguiente código muestra un controlador de vista que contiene un UITableView con 1 fila, y debajo de eso, un UIButton. Al tocar el botón o en la fila, aparecerá una ventana emergente. Esto funciona bien al tocar el botón, pero al tocar la fila de la vista de tabla, aparece la ventana emergente con cierto retraso. En mis pruebas, la primera vez que toco la fila, la ventana emergente generalmente aparece con poco o ningún retraso, pero la segunda vez que toco la fila, pueden pasar muchos segundos antes de que aparezca la ventana emergente y, a menudo, no aparece hasta que toca otra parte en la vista. Sin embargo, la demora puede ocurrir incluso en el primer toque en la fila (especialmente cuando se prueba en hardware).

El código que muestro se ha reducido en la mayor medida posible, al tiempo que se mantiene el problema. Me parece que el UITableView es de alguna manera crítico para hacer que ocurra este retraso.

Sé que parte del código de UIPopoverController está en desuso en iOS 8. He intentado usar UIPopoverPresentationController para iOS 8, y el resultado es el mismo: un retraso a veces muy largo antes de que aparezca la ventana emergente. Todavía no estoy muy familiarizado con este nuevo enfoque, por lo que es posible que esté cometiendo errores, pero en cualquier caso, el código de iOS 8 se puede probar configurando la macro USE_TRADITIONAL_METHOD en 0 en lugar de 1.

Cualquier sugerencia sobre cómo solucionar u omitir esto (mientras se usa una vista de tabla) será muy apreciada.

#import "MyViewController.h" @interface MyViewController () @property (nonatomic) UIPopoverController* myPopoverController; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; // setup table view UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 500, 500) style:UITableViewStyleGrouped]; [self.view addSubview:tableView]; tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; tableView.dataSource = self; tableView.delegate = self; // setup button UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:button]; button.frame = CGRectMake(20, 550, 100, 20); [button setTitle:@"Show popover" forState:UIControlStateNormal]; [button addTarget:self action:@selector(showPopover:) forControlEvents:UIControlEventTouchUpInside]; } - (IBAction)showPopover:(id)sender { UIView* senderView = (UIView*)sender; UIViewController* contentViewController = [[UIViewController alloc] init]; contentViewController.view.backgroundColor = [UIColor purpleColor]; #define USE_TRADITIONAL_METHOD 1 #if USE_TRADITIONAL_METHOD self.myPopoverController = [[UIPopoverController alloc] initWithContentViewController:contentViewController]; [self.myPopoverController presentPopoverFromRect:senderView.frame inView:senderView.superview permittedArrowDirections:UIPopoverArrowDirectionLeft animated:NO]; #else contentViewController.modalPresentationStyle = UIModalPresentationPopover; [self presentViewController:contentViewController animated:NO completion:^{ NSLog(@"Present completion"); // As expected, this is executed once the popover is actually displayed (which can take a while) }]; // do configuration *after* call to present, as explained in Apple documentation: UIPopoverPresentationController* popoverController = contentViewController.popoverPresentationController; popoverController.sourceRect = senderView.frame; popoverController.sourceView = senderView; popoverController.permittedArrowDirections = UIPopoverArrowDirectionLeft; #endif NSLog(@"Popover is visible: %d", self.myPopoverController.isPopoverVisible); // This shows "1" (visible) for USE_TRADITIONAL_METHOD, under both iOS 7 and iOS 8 } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; cell.textLabel.text = @"Show popover"; return cell; } #pragma mark - UITableViewDelegate -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self showPopover:[tableView cellForRowAtIndexPath:indexPath]]; } @end


Muchas gracias por ese truco. Tengo un TableView que muestra una ventana emergente cuando hago clic en una línea. Mi ventana emergente se mostraba solo después de un retraso, o incluso requería un doble clic en la línea para finalmente aparecer. Al agregar la línea indicada ([tableView deselectRowAtIndexPath: indexPath animated: NO]) la ventana emergente se muestra inmediatamente sin tener que hacer doble clic más.


Tuve el mismo problema, y ​​deseleccionar la celda antes de mostrar la ventana emergente no hizo nada para resolver mi problema. Lo que funcionó para mí fue enviar el código emergente a la cola principal con un minúsculo retraso. Esto produce una visualización consistente de la ventana emergente Y me permite mantener la celda SELECCIONADA, que es la clave de mi interfaz de usuario:

IU esperada

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { switch actions[indexPath.row] { case .rename: .... case .duplicate: DispatchQueue.main.asyncAfter(deadline: .now() + 0.01, execute: { let copyController = UIStoryboard.init(name: "Actions", bundle: nil).instantiateViewController(withIdentifier: "copyToNavController") copyController.modalPresentationStyle = .popover let cell = tableView.cellForRow(at: indexPath) copyController.popoverPresentationController?.sourceView = cell if let frame = cell?.frame { copyController.popoverPresentationController?.sourceRect = frame } copyController.popoverPresentationController?.permittedArrowDirections = .left self.popoverPresenter = copyController.popoverPresentationController self.present(copyController, animated: true, completion: nil) }) default: break } }