活动指标视图未显示

时间:2016-08-06 14:43:22

标签: ios swift uiactivityindicatorview

我有这段代码:

    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(),但它仍然没有显示。

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

  

enter image description here

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

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

  

enter image description here

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

有几个可能的问题:

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

  2. 确保异步执行耗时的JSON请求(例如,使用 // Connects to the first link in the list console.log("Request to: " + urls[0]); urls[0] = $.post("php/parser.php", { url: urls[0] }, function(res, state) { console.log(0 + ": completed"); } ); for(var y = 0; y < urls.length;/*y++*/) { $.when(urls[y]).done(function(res) { // Other calls here console.log("Doing stuff"); // Continuing with the next link y++; if(y < urls.length) { console.log("Request to: " + urls[y]); urls[y] = $.post("php/parser.php", { url: urls[y] }, function(res, state) { console.log(y + ": completed"); } ); } }, function(res) {}); } }); 或等效的第三方库)。您必须确保不阻止主线程,因为这会干扰活动指示器视图。

    因此,如果您的代码执行的操作与NSURLSessionNSData(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()
        }
    }
    

    现在,很明显,完成处理程序的第一个参数将匹配API返回的内容(我使用performNetworkRequest(request) { responseObject, error in // use responseObject/error here } // but not here ,但通常是字典或其他丰富的结构),但希望这说明了基本思路:在主线程上启动活动指示器,异步执行请求和解析,并且只有在请求完成后,删除活动指示器。