ios - custom - activity indicator swift 4
¿Cómo mostrar el indicador de actividad mientras se carga tableView? (10)
Cuando cambio entre mis pestañas, se cargan algunos segundos y quiero saber que mis datos se están cargando. Para eso decidí agregar un indicador de actividad.
Escribí una pequeña función:
func showActivityIndicator() {
dispatch_async(dispatch_get_main_queue()) {
self.spinner = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
self.spinner.frame = CGRect(x: 0.0, y: 0.0, width: 80.0, height: 80.0)
self.spinner.center = CGPoint(x:self.loadingView.bounds.size.width / 2, y:self.loadingView.bounds.size.height / 2)
self.loadingView.addSubview(self.spinner)
self.view.addSubview(self.loadingView)
self.spinner.startAnimating()
}
}
Eso mostrará mi indicador. Y trate de usarlo cuando pulsé desde mi infoController al botón:
@IBAction func goToMainFromInfo(sender: AnyObject) {
self.showActivityIndicator()
self.performSegueWithIdentifier("fromMainToInfoWActivity", sender: nil)
self.hideActivityIndicator()
}
}
Lo muestro antes de segue realizar y ocultar después. No me ayuda Cuando intenté usar la sincronización:
@IBAction func goToMainFromInfo(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.showActivityIndicator()
self.performSegueWithIdentifier("fromMainToInfoWActivity", sender: nil)
self.hideActivityIndicator()
}
}
Pero tampoco ayuda. Cuando presiono para tabular, la opacidad se convierte en 0.5 y espero mientras se carga. Pero no veo mi indicador de actividad.
¿Cuál es el problema?
Este código puede ayudarte :)
let indicator:UIActivityIndicatorView = UIActivityIndicatorView (activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
indicator.color = UIColor .magentaColor()
indicator.frame = CGRectMake(0.0, 0.0, 10.0, 10.0)
indicator.center = self.view.center
self.view.addSubview(indicator)
indicator.bringSubviewToFront(self.view)
indicator.startAnimating()
La respuesta de @ brocolli para swift 4.0. Debe usar objc_ antes de obtener o configurar objetos asociados. Según la documentación, las API de obtención y configuración del objeto asociado en Swift son:
func objc_getAssociatedObject(object: AnyObject!, key: UnsafePointer<Void> ) -> AnyObject! func objc_setAssociatedObject(object: AnyObject!, key: UnsafePointer<Void>, value: AnyObject!, policy: objc_AssociationPolicy)
Implementación:
import UIKit fileprivate var ActivityIndicatorViewAssociativeKey = "ActivityIndicatorViewAssociativeKey" extension UIView { var activityIndicatorView: UIActivityIndicatorView { get { if let activityIndicatorView = objc_getAssociatedObject(self, &ActivityIndicatorViewAssociativeKey) as? UIActivityIndicatorView { return activityIndicatorView } else { let activityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) activityIndicatorView.activityIndicatorViewStyle = .gray activityIndicatorView.color = .gray activityIndicatorView.center = center activityIndicatorView.hidesWhenStopped = true addSubview(activityIndicatorView) objc_setAssociatedObject(self, &ActivityIndicatorViewAssociativeKey, activityIndicatorView, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return activityIndicatorView } } set { addSubview(newValue) objc_setAssociatedObject(self, &ActivityIndicatorViewAssociativeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } }
Otro enfoque, en mi código, agregué una extensión para UITableView (Swift 2.3):
extension UITableView {
func activityIndicator(center: CGPoint = CGPointZero, loadingInProgress: Bool) {
let tag = 12093
if loadingInProgress {
var indicator = UIActivityIndicatorView()
indicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 40, 40))
indicator.tag = tag
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
indicator.color = //Your color here
indicator.center = center
indicator.startAnimating()
indicator.hidesWhenStopped = true
self.superview?.addSubview(indicator)
}else {
if let indicator = self.superview?.viewWithTag(tag) as? UIActivityIndicatorView { {
indicator.stopAnimating()
indicator.removeFromSuperview()
}
}
}
}
Nota: Mi vista de tabla está incrustada en una vista UIV (supervisión)
Para colocar el UIActivityIndicator en primer plano, incluso sobre los eventuales separadores UITableViewController, he adoptado esta solución.
He agregado el UIActivityIndicator programáticamente, y lo agrego como una subvista de mi UINavigationController
func objc_getAssociatedObject(object: AnyObject!, key: UnsafePointer<Void> ) -> AnyObject! func objc_setAssociatedObject(object: AnyObject!, key: UnsafePointer<Void>, value: AnyObject!, policy: objc_AssociationPolicy)
Acabo de iniciarlo y detenerlo cuando sea necesario (en mi caso):
import UIKit fileprivate var ActivityIndicatorViewAssociativeKey = "ActivityIndicatorViewAssociativeKey" extension UIView { var activityIndicatorView: UIActivityIndicatorView { get { if let activityIndicatorView = objc_getAssociatedObject(self, &ActivityIndicatorViewAssociativeKey) as? UIActivityIndicatorView { return activityIndicatorView } else { let activityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) activityIndicatorView.activityIndicatorViewStyle = .gray activityIndicatorView.color = .gray activityIndicatorView.center = center activityIndicatorView.hidesWhenStopped = true addSubview(activityIndicatorView) objc_setAssociatedObject(self, &ActivityIndicatorViewAssociativeKey, activityIndicatorView, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return activityIndicatorView } } set { addSubview(newValue) objc_setAssociatedObject(self, &ActivityIndicatorViewAssociativeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } }
PD. Mi entorno es Xcode 10.0, iOS 12.0
Solo prueba esto:
var indicator = UIActivityIndicatorView()
func activityIndicator() {
indicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 40, 40))
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
indicator.center = self.view.center
self.view.addSubview(indicator)
}
Y donde quieres empezar a animar.
indicator.startAnimating()
indicator.backgroundColor = UIColor.whiteColor()
Para la parada:
indicator.stopAnimating()
indicator.hidesWhenStopped = true
Nota: Evite las llamadas de inicio y parada en el mismo tiempo. Solo dale algunas condiciones.
Swift 2+
class ViewController: UITableViewController {
weak var activityIndicatorView: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
tableView.backgroundView = activityIndicatorView
self.activityIndicatorView = activityIndicatorView
activityIndicatorView.startAnimating()
}
...
}
Utilizando "lazy var". Es mejor que funcion
fileprivate lazy var activityIndicatorView: UIActivityIndicatorView = {
let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
activityIndicatorView.hidesWhenStopped = true
// Set Center
var center = self.view.center
if let navigationBarFrame = self.navigationController?.navigationBar.frame {
center.y -= (navigationBarFrame.origin.y + navigationBarFrame.size.height)
}
activityIndicatorView.center = center
self.view.addSubview(activityIndicatorView)
return activityIndicatorView
}()
Simplemente comienza el spinner en cualquier lugar
Me gusta esto
func requestData() {
// Request something
activityIndicatorView.startAnimating()
}
RÁPIDO
Coloca esto debajo de tu clase:
let indicator:UIActivityIndicatorView = UIActivityIndicatorView (activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
Coloca esto en tu loadView ():
indicator.color = UIColor .magentaColor()
indicator.frame = CGRectMake(0.0, 0.0, 10.0, 10.0)
indicator.center = self.view.center
self.view.addSubview(indicator)
indicator.bringSubviewToFront(self.view)
indicator.startAnimating()
En mi caso, estoy solicitando objetos json a través de una solicitud de función, por lo que coloqué esto al final de esa función para eliminar el indicador de actividad una vez que se cargan los datos:
self.indicator.stopAnimating()
self.indicator.hidesWhenStopped = true
Swift 3.0
// Extensión UIView
fileprivate var ActivityIndicatorViewAssociativeKey = "ActivityIndicatorViewAssociativeKey"
public extension UIView {
var activityIndicatorView: UIActivityIndicatorView {
get {
if let activityIndicatorView = getAssociatedObject(&ActivityIndicatorViewAssociativeKey) as? UIActivityIndicatorView {
return activityIndicatorView
} else {
let activityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
activityIndicatorView.activityIndicatorViewStyle = .gray
activityIndicatorView.color = .gray
activityIndicatorView.center = center
activityIndicatorView.hidesWhenStopped = true
addSubview(activityIndicatorView)
setAssociatedObject(activityIndicatorView, associativeKey: &ActivityIndicatorViewAssociativeKey, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return activityIndicatorView
}
}
set {
addSubview(newValue)
setAssociatedObject(newValue, associativeKey:&ActivityIndicatorViewAssociativeKey, policy: .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
// Extensión de NSObject
public extension NSObject {
func setAssociatedObject(_ value: AnyObject?, associativeKey: UnsafeRawPointer, policy: objc_AssociationPolicy) {
if let valueAsAnyObject = value {
objc_setAssociatedObject(self, associativeKey, valueAsAnyObject, policy)
}
}
func getAssociatedObject(_ associativeKey: UnsafeRawPointer) -> Any? {
guard let valueAsType = objc_getAssociatedObject(self, associativeKey) else {
return nil
}
return valueAsType
}
}
iniciar la animación
tableView.activityIndicatorView.startAnimating()
detener la animación
tableView.activityIndicatorView.stopAnimating()
Puedes encontrar más código en Magic
func setupSpinner(){
spinner = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 40, height:40))
spinner.color = UIColor(Colors.Accent)
self.spinner.center = CGPoint(x:UIScreen.main.bounds.size.width / 2, y:UIScreen.main.bounds.size.height / 2)
self.view.addSubview(spinner)
spinner.hidesWhenStopped = true
}