【问题标题】:Activity Indicator view not showing活动指示器视图未显示
【发布时间】:2016-12-12 19:52:05
【问题描述】:

我有这个代码:

    let x = (self.view.frame.width / 2)
    let y = (self.view.frame.height / 2) - (self.navigationController?.navigationBar.frame.height)!

    let activityView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
    activityView.frame = CGRect(x: 200, y: 120, width: 200, height: 200)
    activityView.center = CGPoint(x: x, y: y)
    activityView.color = UIColor.blueColor()
    activityView.layer.zPosition = 1000
    activityView.startAnimating()
    activityView.hidesWhenStopped = false
    activityView.hidden = false
    self.view.addSubview(activityView)
    self.view.bringSubviewToFront(activityView)

创建指示器视图并将其添加到我的应用程序,但它只是没有显示在屏幕上。

在此调用和 stopAnimating() 调用之间有一个(长)JSON 请求。

这是在视频预览层的顶部,这就是为什么我尝试更改 z 索引和 bringSubviewToFront(),但它仍然没有显示。

这是我在调试视图层次结构时得到的结果:

指示器视图显示在那里,所以它必须被添加到主视图中。 (蓝色矩形也是一个单独的 UIView。)

这是我在应用程序上看到的(没有可见的指示器视图!):

我该如何解决这个问题?

【问题讨论】:

    标签: ios swift uiactivityindicatorview


    【解决方案1】:

    有几个可能的问题:

    1. 确保从主线程添加此活动指示器视图。如果此代码在后台线程上运行,请确保将活动指示器相关代码分派回主队列。

    2. 确保异步执行耗时的 JSON 请求(例如,使用 NSURLSession 或等效的第三方库)。您必须确保不会阻塞主线程,因为这会干扰活动指示器视图。

      因此,如果您的代码执行与 NSData(contentsOfURL:)NSURLConnection.sendSynchronousRequest() 等效的操作,请将其替换为 NSURLSession 或等效的第三方库。

      它可能看起来像:

      func performNetworkRequest(request: NSURLRequest, completionHandler: (String?, ErrorType?) -> ()) {
          let spinner = startActivityIndicatorView()
      
          let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
              // regardless of what happens, stop activity indicator view
      
              defer { self.stopActivityIndicatorView(spinner) }
      
              // your parsing code here ...
      
              // when all done, call completion handler
      
              if successful {    
                  completionHandler(..., nil)
              } else {
                  completionHandler(nil, someError)
              }
          }
          task.resume()
      }
      
      // I've simplified this a little bit
      
      func startActivityIndicatorView() -> UIActivityIndicatorView {
          let x = (self.view.frame.width / 2)
          let y = (self.view.frame.height / 2) - (self.navigationController?.navigationBar.frame.height)!
      
          let activityView = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
          activityView.frame = CGRect(x: 200, y: 120, width: 200, height: 200)
          activityView.center = CGPoint(x: x, y: y)
          activityView.color = .blueColor()
          activityView.startAnimating()
          self.view.addSubview(activityView)
      
          return activityView
      }
      
      func stopActivityIndicatorView(activityView: UIActivityIndicatorView) {
          dispatch_async(dispatch_get_main_queue()) {
              activityView.removeFromSuperview()
          }
      }
      

      你会这样使用它:

      performNetworkRequest(request) { responseObject, error in
          // use responseObject/error here
      }
      
      // but not here
      

      现在,很明显,完成处理程序的第一个参数将匹配您的 API 返回的任何内容(我使用了 String?,但通常它是字典或其他一些丰富的结构),但希望这能说明基本思想: 在主线程启动活动指示器,异步执行请求和解析,只有当请求完成时,才移除活动指示器。

    【讨论】:

    • 哇。多谢!!在被困了几个小时后,这真的帮助了我! :D 再次感谢 :)
    猜你喜欢
    • 2023-04-07
    • 2016-06-25
    • 2012-01-25
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多