ios - ¿Cómo volver a dibujar UICollectionViewCell no visible después de que la rotación esté lista para cuando se vuelva a utilizar?
swift prepareforreuse (3)
Cómo volver a dibujar no visible UICollectionViewCell está listo para cuando se produce la reutilización ???
Un enfoque en el que pensé fue por el código de la función Preparar celda prepareForReuse, sin embargo, mientras funciona no es óptimo, ya que causa más re-dibujo que se requiere.
Antecedentes: Necesito desencadenar drawRect
para las celdas después de un cambio de orientación que no está visible actualmente, pero aparece para usar y no se ha vuelto a dibujar, por lo que hasta ahora solo puedo ver que prepareForReuse
sería apropiado. El problema es que estoy volviendo a dibujar todas las celdas de "reutilización", mientras que realmente solo quiero volver a dibujar aquellas que inicialmente aparecieron creadas durante la posición de orientación anterior del dispositivo.
INFORMACIÓN ADICIONAL: Actualmente estoy haciendo esto:
En ViewController:
override func viewWillLayoutSubviews() {
// Clear cached layout attributes (to ensure new positions are calculated)
(self.cal.collectionViewLayout as! GCCalendarLayout).resetCache()
self.cal.collectionViewLayout.invalidateLayout()
// Trigger cells to redraw themselves (to get new widths etc)
for cell in self.cal?.visibleCells() as! [GCCalendarCell] {
cell.setNeedsDisplay()
}
// Not sure how to "setNeedsDisplay" on non visible cells here?
}
En la clase de celda de diseño:
override func prepareForReuse() {
super.prepareForReuse()
// Ensure "drawRect" is called (only way I could see to handle change in orientation
self.setNeedsDisplay()
// ISSUE: It does this also for subsequent "prepareForReuse" after all
// non-visible cells have been re-used and re-drawn, so really
// not optimal
}
Ejemplo de lo que sucede sin el código en prepareForReuse anterior. Instantánea tomada después de un cambio de orientación, y justo después de desplazarse un poco hacia arriba:
Creo que lo tengo ahora aquí:
import UIKit
@IBDesignable class GCCalendarCell: UICollectionViewCell {
var prevBounds : CGRect?
override func layoutSubviews() {
if let prevBounds = prevBounds {
if !( (prevBounds.width == bounds.width) && (prevBounds.height == bounds.height) ) {
self.setNeedsDisplay()
}
}
}
override func drawRect(rect: CGRect) {
// Do Stuff
self.prevBounds = self.bounds
}
}
Tomó nota de que esta comprobación no funcionaba en "prepareForReuse" ya que en este momento no se había aplicado la rotación a la celda. Parece que funciona en "layoutSubviews" sin embargo.
Puede implementar algún tipo de comunicación entre las celdas y el controlador de vista que contiene la vista de recopilación (protocolo y delegado o bloque pasado o incluso referencia directa al CV). Luego, puede solicitarle al controlador de visualización cambios de rotación.
Es un poco desordenado, pero si tiene algún tipo de seguimiento de rotación en su controlador de vista Puede filtrar setNeedsDisplay con una simple instrucción if.
Tenía células de actualización desafiadas similares que ya se mostraban y salían de la pantalla. Aunque es posible que no se puedan realizar ciclos a través de las celdas ALLL, es refrescante / bucle a través de las no visibles. SI este es tu caso de uso, entonces sigue leyendo. Pre-advertencia: si está agregando este tipo de código, explique por qué lo está haciendo. Es una especie de anti patrón, pero puede ayudar a solucionar ese error y ayudar a enviar su aplicación, aunque agregue complejidad innecesaria. No use esto en múltiples lugares en la aplicación.
Cualquier collectionviewcell que se haya desactivado (fuera de la pantalla y se vuelva a conectar) se debe cancelar automáticamente.
Patrón de notificación
let kUpdateButtonBarCell = NSNotification.Name("kUpdateButtonBarCell")
class Notificator {
static func fireNotification(notificationName: NSNotification.Name) {
NotificationCenter.default.post(name: notificationName, object: nil)
}
}
extension UICollectionViewCell{
func listenForBackgroundChanges(){
NotificationCenter.default.removeObserver(self, name: kUpdateButtonBarCell, object: nil)
NotificationCenter.default.addObserver(forName:kUpdateButtonBarCell, object: nil, queue: OperationQueue.main, using: { (note) in
print( " contentView: ",self.contentView)
})
}
}
override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("die", forIndexPath: indexPath) as UICollectionViewCell
cell.listenForBackgroundChanges()
return cell
}
// Where appropriate broadcast notification to hook into all cells past and present
Notificator.fireNotification(notificationName: kUpdateButtonBarCell)
Delegar patrón
Es posible simplificar esto ... un ejercicio para el lector. simplemente no retenga las celdas (use un enlace débil); de lo contrario, tendrá fugas de memoria.