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。)
这是我在应用程序上看到的(看不到指示器视图!):
我该如何解决这个问题?
有几个可能的问题:
确保从主线程添加此 activity 指标视图。如果此代码 运行 在后台线程上,请确保将 activity 指标相关代码分派回主队列。
确保您异步执行耗时的 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 指示器。
我有这个代码:
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。)
这是我在应用程序上看到的(看不到指示器视图!):
我该如何解决这个问题?
有几个可能的问题:
确保从主线程添加此 activity 指标视图。如果此代码 运行 在后台线程上,请确保将 activity 指标相关代码分派回主队列。
确保您异步执行耗时的 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 指示器。