tutorial cocoa-touch ios

cocoa-touch - cocoa touch tutorial



Cómo recibir una notificación cuando scrollToRowAtIndexPath termina de animar (5)

Implementando esto en una extensión Swift.

//strong ref required private var lastDelegate : UITableViewScrollCompletionDelegate! = nil private class UITableViewScrollCompletionDelegate : NSObject, UITableViewDelegate { let completion: () -> () let oldDelegate : UITableViewDelegate? let targetOffset: CGPoint @objc private func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) { scrollView.delegate = oldDelegate completion() lastDelegate = nil } init(completion: () -> (), oldDelegate: UITableViewDelegate?, targetOffset: CGPoint) { self.completion = completion self.oldDelegate = oldDelegate self.targetOffset = targetOffset super.init() lastDelegate = self } } extension UITableView { func scrollToRowAtIndexPath(indexPath: NSIndexPath, atScrollPosition scrollPosition: UITableViewScrollPosition, animated: Bool, completion: () -> ()) { assert(lastDelegate == nil, "You''re already scrolling. Wait for the last completion before doing another one.") let originalOffset = self.contentOffset self.scrollToRowAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: false) if originalOffset.y == self.contentOffset.y { //already at the right position completion() return } else { let targetOffset = self.contentOffset self.setContentOffset(originalOffset, animated: false) self.delegate = UITableViewScrollCompletionDelegate(completion: completion, oldDelegate: self.delegate, targetOffset:targetOffset) self.scrollToRowAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: true) } } }

Esto funciona en la mayoría de los casos aunque el delegado TableView se modifique durante el desplazamiento, lo que puede no desearse en algunos casos.

Esta es una continuación de Cómo recibir una notificación cuando un TableViewController termina de animar la inserción en una pila de navegación.

En tableView , quiero deseleccionar una fila con animación, pero solo después de que tableView haya terminado de animar el desplazamiento a la fila seleccionada. ¿Cómo puedo recibir una notificación cuando eso sucede, o qué método se llama en el momento en que termina?

Este es el orden de las cosas:

  1. Controlador de vista push
  2. En viewWillAppear selecciono una cierta fila.
  3. En viewDidAppear I scrollToRowAtIndexPath (a la fila seleccionada).
  4. Luego, cuando eso termine de desplazarse, quiero deselectRowAtIndexPath: animated:YES

De esta forma, el usuario sabrá por qué se desplazaron allí, pero luego puedo desvanecerme la selección.
El paso 4 es la parte que todavía no he descifrado. Si lo llamo en viewDidAppear cuando viewDidAppear se desplace allí, la fila ya no está seleccionada, lo cual no es bueno.


Para abordar el comentario de Ben Packard sobre la respuesta aceptada, puede hacer esto. Pruebe si tableView puede desplazarse a la nueva posición. Si no, ejecuta tu método de inmediato. Si puede desplazarse, espere hasta que el desplazamiento finalice para ejecutar su método.

- (void)someMethod { CGFloat originalOffset = self.tableView.contentOffset.y; [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:NO]; CGFloat offset = self.tableView.contentOffset.y; if (originalOffset == offset) { // scroll animation not required because it''s already scrolled exactly there [self doThingAfterAnimation]; } else { // We know it will scroll to a new position // Return to originalOffset. animated:NO is important [self.tableView setContentOffset:CGPointMake(0, originalOffset) animated:NO]; // Do the scroll with animation so `scrollViewDidEndScrollingAnimation:` will execute [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; } } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { [self doThingAfterAnimation]; }


Puede incluir scrollToRowAtIndexPath: dentro de un [UIView animateWithDuration:...] que activará el bloque de finalización después de que concluyan todas las animaciones incluidas. Entonces, algo como esto:

[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionAllowUserInteraction animations:^ { // Scroll to row with animation [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; } completion:^(BOOL finished) { // Deselect row [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; }];


Puede usar el método scrollViewDidEndScrollingAnimation: del delegado de la vista de tabla. Esto se debe a que UITableView es una subclase de UIScrollView y UITableViewDelegate cumple con UIScrollViewDelegate . En otras palabras, una vista de tabla es una vista de desplazamiento, y un delegado de vista de tabla es también un delegado de vista de desplazamiento.

Por lo tanto, cree un método scrollViewDidEndScrollingAnimation: en su delegado de vista de tabla y anule la selección de la celda en ese método. Consulte la documentación de referencia para UIScrollViewDelegate para obtener información sobre el método scrollViewDidEndScrollingAnimation: .


prueba esto

[UIView animateWithDuration:0.3 animations:^{ [yourTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO]; } completion:^(BOOL finished){ //do something }];

No se olvide de configurar animada a NO, la animación de scrollToRow será anulada por UIView animateWithDuration.

Espero que esto ayude !