ios - uitabbarcontroller swift 4
Control UIRefresh atascado después de cambiar las pestañas en UITabBarController (14)
Acabo de ver lo mismo. Lo que terminé haciendo es endRefreshing on viewWillDisappear y eso al menos elimina este problema. Sin embargo, volviendo a la pestaña, espero que comience a girar nuevamente cuando reinicio el proceso de actualización y vuelvo a llamar a BeginRefreshing, pero no es así. Lo hace en el caso cuando profundizo la navegación y luego regreso.
Tengo un UITableViewController como controlador de vista raíz en un UINavigationController, que a su vez es uno de los controladores de vista en un UITabBarController. Todo conectado en Storyboard.
También configuré el UIRefreshControl para mi tabla en el Storyboard, y normalmente parece que debería hacerlo al tirar:
Sin embargo, si cambio entre mis otras pestañas una o dos veces, se verá así:
No está girando ni nada, solo se atasca "lleno", y permanece así hasta que lo jale por completo y active una actualización.
Cualquier idea o sugerencia apreciará.
Después de encontrarme con el mismo problema varias veces, decidí crear una biblioteca para ello SwiftPullToRefresh .
Como se dijo antes, refreshControl
debe refreshControl
en viewDidDisappear(_:)
y comenzar en viewWillAppear(_:)
.
Al iniciar la animación refreshControl
programación, tableView.contentOffset
debe configurarse en el valor apropiado.
tableView.setContentOffset(CGPoint(x: 0, y: -(refreshControl?.bounds.height ?? 60) - topOffset), animated: true)
var topOffset: CGFloat {
if let navigationBar = navigationController?.navigationBar, navigationBar.isTranslucent == true {
return navigationBar.bounds.height + UIApplication.shared.statusBarFrame.height
} else {
return 0
}
}
Espero poder ayudar a resolver este problema finalmente:
Hay un problema al utilizar UITableView con un control Pull-To-Refresh. Esto se puede resolver FÁCILMENTE, agregando un UITableViewController.
UITableViewController *tableController = [[UITableViewController alloc] init];
tableController.automaticallyAdjustsScrollViewInsets = NO;
[tableController willMoveToParentViewController:self];
[self addChildViewController:tableController];
tableController.tableView = self.containerTableView;
tableController.refreshControl = self.refreshControl;
De esta manera, simplemente envuelve su UITableView dentro de un controlador para el cual [self.refreshControl endRefreshing]
funcionará completamente bien dentro de viewWillAppear
o viewWillDisappear
. En algunos casos es posible que tenga que llamarlo en ambos.
¡Espero que esto ayude! :)
La mejor solución en Swift:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//fixes bug with refreshControl freezing while switching tabs
if tableView.contentOffset.y < 0 {
tableView.contentOffset = .zero
}
}
La siguiente solución puede ayudarte.
CGFloat yTableViewOffset;
- (void)viewDidLoad {
yTableViewOffset = kNilOptions;
}
- (void)viewWillAppear:(BOOL)animated
{
if(yTableViewOffset != kNilOptions) {
CGPoint offset = CGPointMake(tableView.contentOffset.x, yTableViewOffset);
[refreshControl beginRefreshing];
tableView.contentOffset = offset;
}
}
- (void)viewWillDisappear:(BOOL)animated
{
if(refreshControl.isRefreshing) {
yTableViewOffset = tableView.contentOffset.y;
[refreshControl endRefreshing];
}
}
Las respuestas en esta question resolvieron mi problema.
Básicamente, deteniendo e iniciando el giro nuevamente en viewWillAppear
Mientras el control de actualización está girando, si presenta algún otro controlador y vuelve antes de "finalizar la actualización"; la animación de actualización se atascará.
Ninguna de las respuestas anteriores funcionó para mí, y no quería configurar Bool y seguirlo durante todo el ciclo de vida de un controlador de vista.
Mi solución es agregar el siguiente código al final de viewWillAppear.
en Objc;
if (self.refreshControl.isRefreshing) {
[self.refreshControl endRefreshing];
[self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y-self.refreshControl.frame.size.height) animated: true];
[self.refreshControl beginRefreshing];
}
en Swift;
if self.refreshControl.isRefreshing {
self.refreshControl.endRefreshing
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y-self.refreshControl.frame.size.height), animated: true)
self.refreshControl.beginRefreshing;
}
La lógica es; siempre que atrape el control de actualización está en estado de animación, lo detendrá sin saber si está atascado o no y volverá a ejecutar la animación.
Espero eso ayude.
No pude hacer que la llamada a endRefreshing funcionara antes de que ocurriera la navegación, así que abordé el problema desde el otro extremo y en la vista. Apareceré. Verifico si el valor de TableView contentOffset es un número negativo devuelve el valor de tableView a 0.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.tableView.contentOffset.y < 0)
{
[self.tableView setContentOffset:CGPointZero animated:YES];
}
}
Para resumir y proporcionar una solución completa.
El problema:
Si UIRefreshControl está animando durante la transición de pantalla, permanecerá visible pero no estará animando. Video https://vid.me/Bkb7
Además, si se inició la animación de extracción para actualizar, pero no se completó, y luego se realizó la transición, UIRefreshControl se ocultará pero se atascará. Video https://vid.me/Bkb7
Solución:
Inicie la animación UIRefreshControl en viewWillAppear y finalícela en viewDidDisappear. Guarde el estado del proceso de actualización para saber cuándo mostrar UIRefreshControl.
Bellow es la solución completa que también maneja la animación adecuada y el tirón simple para actualizar la animación.
Añadir a UITableView o subclase
Inicialización:
/// Refresh indicator
var refreshControl = UIRefreshControl()
/// Refresh state
var isRefreshing = false
/// Refresh controll update funcion. Set to enable pull to refresh
var refreshControllUpdateFunction: (() -> ())?
/// Prepeares UIRefreshControll. Call from init
func initRefreshControl(){
addSubview(refreshControl)
refreshControl.addTarget(self, action: "refreshControllTarget", forControlEvents: .ValueChanged)
refreshControl.beginRefreshing()
isRefreshing = true
}
Controladores de eventos de supervisión:
/// Call on viewWillApper
func superviewWillApper(){
if isRefreshing && !refreshControl.refreshing{
startRefreshAnimation()
}
}
/// Call on viewDidDisapper
func superviewDidDisappear(){
endRefreshAnimation(false, dataFetched: !isRefreshing)
}
Controlador de animación UIRefreshControl:
/// Presents animating UIRefreshControll
func startRefreshAnimation(){
refreshControl.beginRefreshing()
contentOffset = CGPointMake(0, -refreshControl.bounds.size.height)
isRefreshing = true
}
/// Hides UIRefreshControll and saves state of refresh
func endRefreshAnimation(wasEmpty: Bool, dataFetched: Bool){
refreshControl.endRefreshing()
isRefreshing = !dataFetched
if !wasEmpty{
setContentOffset(CGPointZero, animated: true)
}else{
setContentOffset(CGPointZero, animated: false)
}
}
Añadir
table.isRefreshing = true
al comienzo de la llamada de actualización.
Resultado del video https://vid.me/LyuI
Quiero algunos puntos y me gusta la solución de Albert pero no su estilo.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_table.contentOffset = CGPointMake(_table.contentOffset.x, _table.contentOffset.y + 1.0f);
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
_table.contentOffset = CGPointMake(_table.contentOffset.x, _table.contentOffset.y - 1.0f);
}
Sé que esto es increíblemente tarde, pero me parece mejor tarde que nunca.
Desafortunadamente, ninguna de las respuestas dadas funcionó para mí. Lo único que funcionó fue este terrible código en viewWillAppear:
self.refreshControl = nil;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(refreshFunction) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
Básicamente, recreo el UIRefreshControl cada vez que aparece la vista. Funciona, aunque da la siguiente advertencia:
Intentar cambiar el control de actualización mientras no está inactivo no se recomienda y probablemente no funcione correctamente.
Sinceramente, me sorprende que esto siga siendo un problema (aún lo veo en iOS 9 ahora). Esperemos que esto pueda ser útil para otras personas.
Simplemente llamando a endRefreshing
en viewWillDisappear:
solucioné todos los problemas para mí.
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.refreshControl endRefreshing];
}
Al hacer lo mismo en viewWillAppear:
el control de actualización viewWillAppear:
extraña al tirar de la mesa.
Tengo un collectionView y configuré su contentInset.
Al presionar algunos ViewControllers, luego presione el botón de inicio, y retroceda y vuelva a aparecer, el control UIRefresh siempre está en la parte superior.
Finalmente utilizo este código temporalmente, evítalo. (Feo pero para siempre siempre se muestra arriba)
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.refreshControl endRefreshing];
CGPoint currentContentOffset = self.collectionView.contentOffset;
[self.collectionView setContentOffset:CGPointMake(currentContentOffset.x,
currentContentOffset.y - 1.0f)
animated:YES];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGPoint currentContentOffset = self.collectionView.contentOffset;
[self.collectionView setContentOffset:CGPointMake(currentContentOffset.x,
currentContentOffset.y + 1.0f)
animated:YES];
}
user2009606 estaba casi correcto, lo arreglé llamando
[refreshControl endRefreshing];
En
viewWillAppear:
El refreshControl ahora se comporta correctamente después de cambiar las pestañas, independientemente de su estado.