无法在 API 调用结束时隐藏 Activity 指示器
Cannot Hide Activity indicator at end of API call
我有一个 table 视图,其中数据是从 API 调用加载的。我显示了一个 正在加载叠加视图。我使用下面的代码来设置加载整体视图。
https://coderwall.com/p/su1t1a/ios-customized-activity-indicator-with-swift
但问题是,一旦加载了 table 视图,我似乎无法隐藏叠加视图或 activity 指示器。它一直在加载。
要启动 activity 指标,使用以下代码:
ViewControllerUtils().showActivityIndicator(self.view)
停止:
ViewControllerUtils().hideActivityIndicator(self.view)
我的API调用代码如下:
import UIKit
class BioListTableViewController: UITableViewController {
// variable to hold the index value of the cell tapped
var cellTapped = Int()
@IBOutlet var tableview: UITableView!
var bioArray = NSArray(){
didSet{
dispatch_async(dispatch_get_main_queue()){
self.tableview.reloadData()
}}}
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.rowHeight = 80.0
// A switch Statement to check which cell was tapped and which API link to call
switch cellTapped
{
case 0:
test()
case 1:
test()
default:
test()
}
}
override func viewDidAppear(animated: Bool)
{
ViewControllerUtils().hideActivityIndicator(self.view)
}
func test() {
ViewControllerUtils().showActivityIndicator(self.view)
println("This is TWEST")
var request = NSMutableURLRequest(URL: NSURL(string: "APILink")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "GET"
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
var err: NSError?
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSArray
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
dispatch_async(dispatch_get_main_queue()) {
var alert = UIAlertController(title: "Alert", message: "Seems to be an error with server. Try Again Later", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}}
else {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
//To to long tasks
// LoadingOverlay.shared.hideOverlayView()
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
//var newWeather = WeatherSummary(id:"")
if let parseJSON = json {
self.bioArray = parseJSON
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}}
})
task.resume()
}
func testTwo(){
println("THIS IS TEST 2")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return self.bioArray.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("bioCell", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
let weatherSummary: AnyObject = bioArray[indexPath.row]
if let id = weatherSummary["employeeName"] as? String
{
cell.textLabel?.text = id
}
if let job = weatherSummary["sector"] as? String {
cell.detailTextLabel?.text = job
}
var fram = cell.imageView?.frame
//fram? = CGRectMake( 0, 0, 50, 55 )
let imageSize = 50 as CGFloat
fram?.size.height = imageSize
fram?.size.width = imageSize
cell.imageView!.frame = fram!
cell.imageView!.layer.cornerRadius = imageSize / 2.0
cell.imageView!.clipsToBounds = true
//cell.imageView?.image = UIImage(named: "userIcon.png")
if let userImage = weatherSummary["userImage"] as? String{
if let url = NSURL(string: userImage){
if let data = NSData(contentsOfURL: url){
if let image:UIImage = UIImage(data: data){
cell.imageView?.image = image
}
}
}
}
return cell
}
尝试在主队列上关闭并在收到服务器响应时关闭它
dispatch_async(dispatch_get_main_queue(), {
ViewControllerUtils().hideActivityIndicator(self.view)
}))
您可以使用我从某处获得的另一个自定义 activity 指标。最简单有效的一种。 (虽然它有带指示器的文本,但如果您不想显示文本,则可以按您的方式自定义)
制作class
class customActivityIndicator: UIVisualEffectView {
var text: String? {
didSet {
label.text = text
}
}
let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
let label: UILabel = UILabel()
let blurEffect = UIBlurEffect(style: .Dark)
let vibrancyView: UIVisualEffectView
init(text: String) {
self.text = text
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(effect: blurEffect)
self.setup()
}
required init(coder aDecoder: NSCoder) {
self.text = ""
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(coder: aDecoder)
self.setup()
}
func setup() {
contentView.addSubview(vibrancyView)
vibrancyView.contentView.addSubview(activityIndicator)
vibrancyView.contentView.addSubview(label)
activityIndicator.startAnimating()
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superview = self.superview {
let width: CGFloat = 150
let height: CGFloat = 50.0
self.frame = CGRectMake(superview.frame.size.width / 2 - width / 2,
superview.frame.height / 2 - height,
width,height)
vibrancyView.frame = self.bounds
let activityIndicatorSize: CGFloat = 40
activityIndicator.frame = CGRectMake(5, height / 2 - activityIndicatorSize / 2,
activityIndicatorSize,
activityIndicatorSize)
layer.cornerRadius = 8.0
layer.masksToBounds = true
label.text = text
label.textAlignment = NSTextAlignment.Center
label.frame = CGRectMake(activityIndicatorSize + 5, 0, width - activityIndicatorSize - 20, height)
label.textColor = UIColor.grayColor()
label.font = UIFont.boldSystemFontOfSize(16)
}
}
func show() {
self.hidden = false
}
func hide() {
self.hidden = true
}
}
要使用这个:
let spinner = customActivityIndicator(text: "Loading")
//To start animating
self.view.addSubview(spinner)
//To hide
self.spinner.hide()
这可能对你有帮助。
我有一个 table 视图,其中数据是从 API 调用加载的。我显示了一个 正在加载叠加视图。我使用下面的代码来设置加载整体视图。
https://coderwall.com/p/su1t1a/ios-customized-activity-indicator-with-swift
但问题是,一旦加载了 table 视图,我似乎无法隐藏叠加视图或 activity 指示器。它一直在加载。
要启动 activity 指标,使用以下代码:
ViewControllerUtils().showActivityIndicator(self.view)
停止:
ViewControllerUtils().hideActivityIndicator(self.view)
我的API调用代码如下:
import UIKit
class BioListTableViewController: UITableViewController {
// variable to hold the index value of the cell tapped
var cellTapped = Int()
@IBOutlet var tableview: UITableView!
var bioArray = NSArray(){
didSet{
dispatch_async(dispatch_get_main_queue()){
self.tableview.reloadData()
}}}
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.rowHeight = 80.0
// A switch Statement to check which cell was tapped and which API link to call
switch cellTapped
{
case 0:
test()
case 1:
test()
default:
test()
}
}
override func viewDidAppear(animated: Bool)
{
ViewControllerUtils().hideActivityIndicator(self.view)
}
func test() {
ViewControllerUtils().showActivityIndicator(self.view)
println("This is TWEST")
var request = NSMutableURLRequest(URL: NSURL(string: "APILink")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "GET"
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
var err: NSError?
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSArray
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
dispatch_async(dispatch_get_main_queue()) {
var alert = UIAlertController(title: "Alert", message: "Seems to be an error with server. Try Again Later", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}}
else {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
//To to long tasks
// LoadingOverlay.shared.hideOverlayView()
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
//var newWeather = WeatherSummary(id:"")
if let parseJSON = json {
self.bioArray = parseJSON
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}}
})
task.resume()
}
func testTwo(){
println("THIS IS TEST 2")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return self.bioArray.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("bioCell", forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
let weatherSummary: AnyObject = bioArray[indexPath.row]
if let id = weatherSummary["employeeName"] as? String
{
cell.textLabel?.text = id
}
if let job = weatherSummary["sector"] as? String {
cell.detailTextLabel?.text = job
}
var fram = cell.imageView?.frame
//fram? = CGRectMake( 0, 0, 50, 55 )
let imageSize = 50 as CGFloat
fram?.size.height = imageSize
fram?.size.width = imageSize
cell.imageView!.frame = fram!
cell.imageView!.layer.cornerRadius = imageSize / 2.0
cell.imageView!.clipsToBounds = true
//cell.imageView?.image = UIImage(named: "userIcon.png")
if let userImage = weatherSummary["userImage"] as? String{
if let url = NSURL(string: userImage){
if let data = NSData(contentsOfURL: url){
if let image:UIImage = UIImage(data: data){
cell.imageView?.image = image
}
}
}
}
return cell
}
尝试在主队列上关闭并在收到服务器响应时关闭它
dispatch_async(dispatch_get_main_queue(), {
ViewControllerUtils().hideActivityIndicator(self.view)
}))
您可以使用我从某处获得的另一个自定义 activity 指标。最简单有效的一种。 (虽然它有带指示器的文本,但如果您不想显示文本,则可以按您的方式自定义)
制作class
class customActivityIndicator: UIVisualEffectView {
var text: String? {
didSet {
label.text = text
}
}
let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
let label: UILabel = UILabel()
let blurEffect = UIBlurEffect(style: .Dark)
let vibrancyView: UIVisualEffectView
init(text: String) {
self.text = text
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(effect: blurEffect)
self.setup()
}
required init(coder aDecoder: NSCoder) {
self.text = ""
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
super.init(coder: aDecoder)
self.setup()
}
func setup() {
contentView.addSubview(vibrancyView)
vibrancyView.contentView.addSubview(activityIndicator)
vibrancyView.contentView.addSubview(label)
activityIndicator.startAnimating()
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
if let superview = self.superview {
let width: CGFloat = 150
let height: CGFloat = 50.0
self.frame = CGRectMake(superview.frame.size.width / 2 - width / 2,
superview.frame.height / 2 - height,
width,height)
vibrancyView.frame = self.bounds
let activityIndicatorSize: CGFloat = 40
activityIndicator.frame = CGRectMake(5, height / 2 - activityIndicatorSize / 2,
activityIndicatorSize,
activityIndicatorSize)
layer.cornerRadius = 8.0
layer.masksToBounds = true
label.text = text
label.textAlignment = NSTextAlignment.Center
label.frame = CGRectMake(activityIndicatorSize + 5, 0, width - activityIndicatorSize - 20, height)
label.textColor = UIColor.grayColor()
label.font = UIFont.boldSystemFontOfSize(16)
}
}
func show() {
self.hidden = false
}
func hide() {
self.hidden = true
}
}
要使用这个:
let spinner = customActivityIndicator(text: "Loading")
//To start animating
self.view.addSubview(spinner)
//To hide
self.spinner.hide()
这可能对你有帮助。