首页 > 解决方案 > UIActivityIndi​​cator 需要几秒钟才能被解除

问题描述

我有一些代码可以OperationQueue使用UIAlertController.

dismiss()问题是微调器在被调用后在屏幕上显示了很长时间。

下面我展示了我正在运行的代码,以及我在模拟器中运行代码时得到的输出。

此功能位于ViewController

@IBAction func runTheTest(_ sender: Any) {

  // MARK: Define web interaction parameters
  let config = URLSessionConfiguration.default
  config.waitsForConnectivity = true
  let defaultSession = URLSession(configuration: config)
  let url = URL(string: "https://www.google.com")
  var getUrlRequest = URLRequest(url: url!)
  getUrlRequest.httpMethod = "GET"

  // MARK: operations CREATION
  let getFormOp = GetFormOperation(getRequest: getUrlRequest, defaultSession: defaultSession, credentials: ["test":"test"], viewController: self)
  let finishOp = FinishOperation(viewController: self)

  // MARK: operations SET DEPENDENCIES
  finishOp.addDependency(getFormOp) // finish op is dependent on get op finishing
  getFormOp.defineFollowOnOperation(finishOp) // This would be if we needed to share data between the two

  // MARK: start the SPINNER
  LoaderController.sharedInstance.showLoader(viewController: self, title: "Please Wait...", message: "Getting data from the web")

  // MARK: initiate the long-running set of operations
  let operationQueue = OperationQueue()
  operationQueue.addOperations([getFormOp, finishOp], waitUntilFinished: false)

  print("operations are running")
}

这是管理活动指示器的类:

class LoaderController: NSObject {

  static let sharedInstance = LoaderController()
  private let activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 10, y: 5, width: 50, height: 50))
  private var start = DispatchTime.now()

  func showLoader(viewController: ViewController, title: String, message: String) {
    start = DispatchTime.now()
    activityIndicator.hidesWhenStopped = true
    activityIndicator.activityIndicatorViewStyle = .gray
    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    self.activityIndicator.startAnimating()
    alert.view.addSubview(activityIndicator)
    viewController.present(alert, animated: true, completion: nil)
    print("load indicator presented")
  }

  func removeLoader(viewController: ViewController){
    let removeCalled = DispatchTime.now()
    let spinnerSeconds =  (removeCalled.uptimeNanoseconds - start.uptimeNanoseconds) / 1000000000
    print("load indicator remove request after \(spinnerSeconds) seconds.")
    viewController.dismiss(animated: true, completion: {
      let finallyGone = DispatchTime.now()
      let spinnerSeconds =  (finallyGone.uptimeNanoseconds - removeCalled.uptimeNanoseconds) / 1000000000
      print("load indicator gone after \(spinnerSeconds) additional seconds.")
    })
  }
}

输出如下所示:

load indicator presented
operations are running
load indicator remove request after 6 seconds.
load indicator gone after 4 additional seconds.

我在模拟器中观察到的与打印语句一致;操作完成,但微调器会再保持 4 秒。

我在这里做错了什么,我该如何解决?

如果该问题缺少您认为必要的任何属性,我将致力于改进该问题,或者在适当的情况下删除该问题,因此请使用评论告诉我。

标签: swiftswift4nsoperationqueueuiactivityindicatorview

解决方案


removeLoader,与所有 UI 操作一样,只能从主线程调用。如果您从一个Operation(而不是 on OperationQueue.main)调用该方法,它应该如下所示:

DispatchQueue.main.async {
   viewController.removeLoader(...)
}

这种延迟几乎总是暗示您正在从后台队列执行 UI 操作。

在模拟器上调试时打开主线程检查器也是一个好主意。


推荐阅读