Tengo un UIViewController que contiene un NSFetchedResultsController . Después de la inserción de filas en la parte superior, quiero mantener las filas visibles como estaban antes de las inserciones. Esto significa que necesito hacer algunos cálculos para mantener contentOffSetY justo después de la actualización. El cálculo es correcto, pero noté que se llama a scrollViewDidScroll después de que se desplazó a mi contentOffsetY especificado, lo que da como resultado un estado corrupto. Este es el registro:
Will apply an corrected Y value of: 207.27359771728516 Scrolled to: 207.5 Corrected to: 207.27359771728516 Scrolled to: 79.5 <-- Why is this logline here? Puede clonar directamente un proyecto de ejemplo: https://github.com/Jaspeav/FetchResultControllerGlitch (commit https://github.com/Jaspeav/FetchResultControllerGlitch/commit/d46054040139afeeb648e1e0b5b113bd98685b4a , la versión más reciente del proyecto solo falla, la extraña llamada a el método scrollViewDidScroll ya no está. Si soluciona el problema técnico, le otorgaré la recompensa. Simplemente clone la versión más reciente, ejecútela y desplácese un poco. Verá compensaciones de contenido extraño (problemas técnicos ). Ejecute el proyecto y verá el resultado extraño. Este es el método controllerDidChangeContent :
public func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { let currentSize = tableView.contentSize.height UIView.performWithoutAnimation { tableView.endUpdates() let newSize = tableView.contentSize.height let correctedY = tableView.contentOffset.y + newSize - currentSize print("Will apply an corrected Y value of: \(correctedY)") tableView.setContentOffset(CGPoint(x: 0, y: correctedY), animated: false) print("Corrected to: \(correctedY)") } } Si llamo a tableView.layoutIfNeeded justo después de tableView.endUpdates() , ya se llamó al delegado. ¿Qué provoca llamar al método de delegado? ¿Hay alguna forma de que no se desplace?
Descargué su código e hice algunos ajustes para solucionar el problema de fallas. Esto es lo que he hecho.
estimatedRowHeight de la vista de tabla en algún número init() { super.init(frame: .zero, style: .plain) estimatedRowHeight = 50.0 register(MyTableViewCell.self, forCellReuseIdentifier: "cell") } func reloadDataWithoutScroll() { let lastScrollOffset = contentOffset beginUpdates() reloadData() layoutIfNeeded() endUpdates() layer.removeAllAnimations() setContentOffset(lastScrollOffset, animated: false) }controllerDidChangeContent para hacer uso de la función reloadDataWithoutScroll UIView.performWithoutAnimation { tableView.performBatchUpdates({ tableView.insertRows(at: inserts, with: .automatic) }) inserts.removeAll() tableView.reloadDataWithoutScroll() }Cuando ejecuto con estos cambios, no se desplaza cuando se agrega una nueva fila. Sin embargo, se desplaza para mostrar la nueva fila agregada cuando el contentOffset actual es 0. Y no creo que eso sea un problema, lógicamente hablando.