Activity 指标视图未显示

Activity Indicator view not showing

我有这个代码:

    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。)

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

我该如何解决这个问题?

有几个可能的问题:

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

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

    因此,如果您的代码正在执行与 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? 但通常它会是字典或其他一些丰富的结构) ,但希望这能说明基本思想:在主线程上启动 activity 指示器,异步执行请求和解析,只有在请求完成后,才删除 activity 指示器。