app ios swift uinavigationcontroller sdwebimage

ios - app store



La aplicaciĆ³n para iOS se congela en PushViewController (5)

Estaba pensando en la congelación intermitente , el hilo principal y SDWebImage .

Suponiendo que está usando la imagen que descargó de downloadImageWithURL: opciones: progreso: completado: bloque completado ... si es así, asegúrese de enviar a la cola principal antes de usar la imagen.

Si utiliza el SDWebImageDownloader directamente, el bloque de finalización (como ha señalado) se invocará en una cola en segundo plano, puede solucionarlo utilizando dispatch_async en la cola principal desde la finalización.

De lo contrario, puede usar: SDWebImageManager downloadImageWithURL: opciones: progreso: completado: (método que invoca los bloques de finalización en la cola principal).

si el problema persiste (solo porque está hablando de "... algunas cosas únicas sobre mi aplicación es que tiene mucha imagen ...") mire también Problemas comunes, especialmente los problemas de actualización de imagen de la manija .

Agregue a su cheque también este bonito código de fragmento:

import UIKit.UINavigationController public typealias VoidBlock = (Void -> Void) public extension UINavigationController { public func pushViewController(viewController: UIViewController, animated: Bool, completion: VoidBlock) { CATransaction.begin() CATransaction.setCompletionBlock(completion) self.pushViewController(viewController, animated: animated) CATransaction.commit() } }

tal vez pueda ayudar a entender si pushViewController finaliza, si finaliza con todos los viewControllers esperados.

Otra prueba que intento hacer es iniciar la aplicación con iOS 8.xy iPhone 6+, porque hay algunos issues en el proyecto pureLayout en iOS 9. ¿Pueden enviar comentarios sobre esta prueba?

También sospecho de la dimensión de vista de desplazamiento real antes de la acción de vista de inserción, ¿puede analizar la vista actual examinando la jerarquía de vistas ?

Mi controlador de navegación se congelará de forma intermitente al presionar. Parece agregar el nuevo controlador de vista a la pila, pero la animación nunca tiene lugar. También tengo otros dos contenedores que contienen controladores de vista en la pantalla, y puedo interactuar con ambos muy bien después de que el controlador de navegación se congele. Lo realmente interesante es que si intento insertar otro controlador de vista en la pila del controlador de navegación, noté que hay un controlador de vista adicional en la parte superior de la pila (el controlador de vista que presioné inicialmente que congeló el controlador de navegación). Entonces, si estoy en la pantalla de inicio (lo llamaremos VC-Home) e intento presionar una nueva vista (VC-1) y se congela, entonces trato de presionar una nueva vista (VC-2), Esto es lo que veo en la pila actual antes del empuje:

{ [VC-Home, VC-1] }

y después de llamar a pushViewController, permanece igual; VC-2 no se agrega a la pila.

Por lo que puedo decir, el controlador de navegación inicia la animación haciendo que el controlador de vista anterior esté inactivo antes de que comience la animación, pero luego la animación nunca tiene lugar, dejando el controlador de navegación en estado congelado.

Estoy creando el nuevo controlador de vista desde un guión gráfico llamando a UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") así que no creo que haya ningún problema allí. Tampoco estoy anulando pushViewController en la barra de navegación. Algunas cosas únicas de mi aplicación es que es muy pesada en imágenes de alta resolución (usando SDWebImage para administrar eso) y siempre tengo tres contenedores en la pantalla a la vez (un controlador de navegación, un controlador de vista para búsqueda y un canal interactivo / menú lateral / deslizable).

El uso de la CPU es bajo y el uso de la memoria es normal (constantemente alrededor de 60-70 MB en el dispositivo cuando se producen bloqueos).

¿Hay alguna idea de lo que podría estar causando esto o algún consejo de depuración que pueda ayudarme a descubrir el verdadero problema?

Actualizar

No hay un código único para UINavigationController ya que solo estoy presionando con pushViewController (). Aquí está el código que lo llama:

func didSelectItem(profile: SimpleProfile) { let vc = UIStoryboard.profileViewController() vc.profile = profile navigationController?.pushViewController(vc, animated: true) }

El ViewController que introduje tiene el siguiente código en viewDidLoad:

override func viewDidLoad() { super.viewDidLoad() button.roundView() if let type = profile?.profileType { //load multiple view controllers into a view pager based on type let viewControllers = ProfileTypeTabAdapter.produceViewControllersBasedOnType(type) loadViewPagerViews(viewControllers) let topInset = headerView.bounds.height + tabScrollView.contentSize.height if let viewPager = viewPager { for view in viewPager.views { if let tempView = view as? PagingChildViewController { tempView.profile = fullProfile tempView.parentVCDelegate = self tempView.topInset = topInset } } } } } func loadViewPagerViews(viewControllers: [UIViewController]) { viewPager?.views = viewControllers viewPager?.delegate = self //loading views into paging scroll view (using PureLayout to create constraints) let _ = subviews.map { $0.removeFromSuperview() } var i = 0 for item in views { addSubview(item.view) item.view.autoSetDimensionsToSize(CGSize(width: tabWidth, height: tabHeight)) if i == 0 { item.view.autoPinEdgeToSuperviewEdge(.Leading) } else if let previousView = views[i-1].view { item.view.autoPinEdge(.Leading, toEdge: .Trailing, ofView: previousView) } if i == views.count { item.view.autoPinEdgeToSuperviewEdge(.Trailing) } i += 1 } contentSize = CGSize(width: Double(i)*Double(tabWidth), height: Double(tabHeight)) }

Actualización 2

Finalmente conseguí congelar de nuevo. La aplicación estaba en segundo plano y la traje de vuelta e intenté presionar un controlador de vista en la pila cuando se congeló. Noté que se estaba produciendo una animación. Tengo una vista de desplazamiento en la parte superior de la página que muestra su contenido cada 10 segundos (piense en el banner superior de las tiendas de aplicaciones). En este congelamiento, noté que el banner estaba a mitad de la animación.

Aquí está la función de desplazamiento de mi UIScrollView que se llama cada 10 segundos:

func moveToNextItem() { let pageWidth: CGFloat = CGRectGetWidth(frame) let maxWidth: CGFloat = pageWidth * CGFloat(max(images.count, profileImages.count)) let contentOffset: CGFloat = self.contentOffset.x let slideToX = contentOffset + pageWidth //if this is the end of the line, stop the timer if contentOffset + pageWidth == maxWidth { timer?.invalidate() timer = nil return } scrollRectToVisible(CGRectMake(slideToX, 0, pageWidth, CGRectGetHeight(frame)), animated: true) }

No recuerdo haber tenido una parada de empuje debido a una animación / desplazamiento, pero podría estar equivocado.

También volví a comprobar la pila y la misma situación que la descrita anteriormente sigue siendo el caso donde [VC-Home, VC-1] es la pila y no se presiona VC-2. También he revisado las variables de VC-1 y todo se ha cargado (llamadas de datos y cargas de imágenes).

Actualización 3

Esto se está volviendo extraño por segundos. He anulado pushViewController para poder poner un punto de interrupción allí y hacer una depuración basada en la respuesta de Alessandro Ornano. Si presiono un controlador de vista sin éxito, luego envío mi aplicación a un segundo plano, coloco un punto de interrupción en la llamada pushViewController y recupero la aplicación, el punto de interrupción es alcanzado varias veces de inmediato. Si luego continúo pasando todos los golpes, el siguiente controlador de vista de repente se vuelve visible y el último controlador de vista que intenté presionar ahora está en la pila como el último controlador de vista. Esto significa que el que veo todavía está desactivado, lo que esencialmente me coloca en la misma posición que antes.


Gran answer de @Penkey Suresh! Me salvó el día! Aquí hay una versión de SWIFT 3 con una pequeña adición que marcó la diferencia para mí:

func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { if (navigationController.viewControllers.count > 1) { self.navigationController?.interactivePopGestureRecognizer?.delegate = self navigationController.interactivePopGestureRecognizer?.isEnabled = true; } else { self.navigationController?.interactivePopGestureRecognizer?.delegate = nil navigationController.interactivePopGestureRecognizer?.isEnabled = false; } }

Simplemente no olvide agregar UINavigationControllerDelegate y establecer el navigationController?.delegate = self Otra parte importante es asignar el interactivePopGestureRecognizer a self o a nil en consecuencia.


Hemos enfrentado el mismo problema hace un par de semanas. Y para nuestro problema, lo redujimos al left-edge pop gesture recogniser . Puede intentar comprobar si puede reproducir este problema siguiendo los pasos a continuación.

  • Intente usar el gesto emergente del borde izquierdo cuando no haya controladores de vista debajo de él (es decir, en los controladores de vista raíz, su controlador VC-Home )
  • Intente hacer clic en cualquier elemento de la interfaz de usuario después de esto.

Si puede reproducir la congelación, intente deshabilitar interactivePopGestureRecognizer cuando la pila del controlador de vista solo tenga un controlador de vista.

Consulte this pregunta para más detalles. A continuación se muestra el código del enlace para facilitar la referencia.

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animate { if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) { if (self.viewControllers.count > 1) { self.interactivePopGestureRecognizer.enabled = YES; } else { self.interactivePopGestureRecognizer.enabled = NO; } } }


Probar en hilo principal

dispatch_async(dispatch_get_main_queue()){ UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") // your code }


Verifique si tiene códigos innecesarios como los siguientes en su BaseNavigationViewController:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true }

Aquí tengo un código de muestra que reproduce este problema (aplicación de congelación al presionar VC) que tiene que reproducirlo siguiendo estos pasos:

  • Intente usar el gesto emergente de borde (izquierdo | derecho) cuando no haya controladores de vista debajo de él (es decir, en los controladores de vista raíz, su controlador VC-Home)
  • Intente hacer clic en cualquier elemento de la interfaz de usuario después de esto (que lo empuja al siguiente ViewController).

Código de muestra: https://github.com/aliuncoBamilo/TestNavigationPushBug