Utilizo el segundo elemento del botón de la barra derecha como indicador cuando hay una sincronización exitosa de CloudKit. Sin embargo, si el TableView se mantiene en desplazamiento (con los elementos ahora debajo de la barra de navegación) cuando aparece el indicador, el TableView rebota en sincronización con la animación. Esto no sucede si el usuario no está interactuando con tableView.

Aquí hay un GIF que demuestra el efecto.

Animated screenshot

Los otros UIBarButtonItem s están configurados en el guión gráfico. El de mi indicador de sincronización de iCloud está configurado en el código en viewDidLoad():

var cloudIndicator = UIImageView()
cloudIndicator.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
cloudIndicator.contentMode = .center
cloudIndicator.transform = CGAffineTransform.identity
// Get existing right bar button item which was set up in storyboard
var rightButtonItems = self.navigationItem.rightBarButtonItems ?? []
let customButtonItem = UIBarButtonItem(customView: cloudIndicator)
rightButtonItems.append(customButtonItem)
self.navigationItem.rightBarButtonItems = rightButtonItems

Este es el método que anima el indicador de sincronización en la nube:

func cloudLabelImageAlert(_ image: UIImage, tintColor: UIColor = .darkGray) {
    DispatchQueue.main.async {
        self.cloudIndicator.alpha = 0
        self.cloudIndicator.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
        self.cloudIndicator.tintColor = tintColor
        self.cloudIndicator.image = image
        // Animate icon appearing
        UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 10, options: [], animations: {
            self.cloudIndicator.alpha = 1
            self.cloudIndicator.transform = CGAffineTransform.identity
        }, completion: { didFinish in
            // Animate icon disappearing
            UIView.animate(withDuration: 0.4, delay: 2.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0, options: [], animations: {
                self.cloudIndicator.alpha = 0
                self.cloudIndicator.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
            }, completion: nil)
        })
    }
)

Presumiblemente, este problema se relaciona con el cambio en el marco de la vista de imagen durante la animación, pero parece extraño que solo ocurra mientras se interactúa con tableView.

¿Hay alguna manera de evitar que esto suceda, o una mejor manera de animar una vista de imagen como un elemento de botón de barra?


Editar

Gracias a los consejos en los comentarios, resulta que esto se debe a la recarga de la vista de tabla y nada que ver con la animación.

Encontré el código problemático, que se llama después de una sincronización de CloudKit:

if let index = self.tableView.indexPathForSelectedRow {
    self.tableView.deselectRow(at: index, animated: true)
    DispatchQueue.main.asyncAfter(deadline: .now()+1) {
        self.tableView.reloadData() // This is delayed as it was causing problems with autoselection (e.g. after coming from Spotlight or notification)
        let image = UIImage(named: "cloudTick")!
        self.cloudLabelImageAlert(image, tintColor: self.colors[0])
    }
} else {
    self.tableView.reloadData()
    let image = UIImage(named: "cloudTick")!
    self.cloudLabelImageAlert(image, tintColor: self.colors[0])
}

Al comentar las líneas self.tableview.reloadData() se detuvo la falla, pero la animación continuó como se esperaba.

Necesito actualizar los datos en este punto para el usuario. ¿Hay una mejor manera de hacer esto?

2
Chris 8 sep. 2018 a las 11:38

3 respuestas

La mejor respuesta

Como se mencionó en la sección de comentarios, probablemente invocaste el método cloudLabelImageAlert(image:, tintColor:) al cargar nuevas celdas de tabla.

Acerca de actualizar los datos, sugeriría invocar el método de vista de tabla reloadData() después de que se complete la animación en la nube.

1
Sharkes Monken 27 sep. 2018 a las 02:57

Hola, tuve una falla similar, pero para mí se solucionó poniendo self.automaticallyScrollInsets en false en viewDidLoad y mientras animaba imageView para ocultar y mostrar en el bloque final de finalización UIView.animate llamé reloadData (). Espero que esto ayude y gracias!

1
Ashish 27 sep. 2018 a las 15:41

Parece que por alguna misteriosa razón su barra de navegación muestra un "título grande" por un momento, lo que lleva a un cambio de ContentInset de tableView.
Por lo tanto, intente deshabilitar manualmente los títulos grandes en viewDidLoad:

if #available(iOS 11.0, *) {
     navigationItem.largeTitleDisplayMode = .never
     navigationController?.navigationBar.prefersLargeTitles = false
}
2
arturdev 26 sep. 2018 a las 20:15