活动指示器视图未显示

3
我有这段代码:
    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个回答

1
有几个可能的问题:
  1. Make sure you add this activity indicator view from the main thread. If this code is running on a background thread, make sure to dispatch the activity indicator related code back to the main queue.

  2. Make sure you perform the time consuming JSON request asynchronously (e.g. using NSURLSession or equivalent third party library). You must make sure that you do not block the main thread because that will interfere with the activity indicator view.

    So if you have code that is doing something equivalent to NSData(contentsOfURL:) or NSURLConnection.sendSynchronousRequest(), replace it with NSURLSession or equivalent third party library).

    It might look something like:

    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()
        }
    }
    

    And you'd use it like so:

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

    Now, clearly that first parameter of the completion handler will match whatever what's being returned by your API (I used a String? but often it would be a dictionary or some other rich structure), but hopefully this illustrates the basic idea: Start activity indicator on main thread, perform the request and parsing asynchronously, and only when the request is done, remove the activity indicator.


哇,非常感谢!在卡了好几个小时之后,这真的帮了我很多!:D 再次感谢 :) - ᔕᖺᘎᕊ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接