Skywalker
Skywalker

Reputation: 5194

Cannot Hide Activity indicator at end of API call

I have a table view where the data is loaded from an API call. I am displayed a Loading Overlay View. I used the following code to set up the loading overall view.

https://coderwall.com/p/su1t1a/ios-customized-activity-indicator-with-swift

But the issue is that I can't seem to hide the overlay view or activity indicator once the table view has been loaded. It just keeps on loading.

To start the activity indicator the following code is used:

 ViewControllerUtils().showActivityIndicator(self.view)

To Stop it:

 ViewControllerUtils().hideActivityIndicator(self.view)

My API call code is below:

 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
}

Upvotes: 0

Views: 2042

Answers (2)

iRiziya
iRiziya

Reputation: 3245

You can use another custom activity indicator that I have got from somewhere. The simplest and effective one. (Though It has the text with the indicator, if you dont want text to be shown then you can customize it your way)

Make a 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
}
 }

To use this :

let spinner = customActivityIndicator(text: "Loading")
//To start animating
self.view.addSubview(spinner)

 //To hide
 self.spinner.hide()

This may help you.

Upvotes: 1

iAnurag
iAnurag

Reputation: 9356

Try to dismiss on main queue and dissmiss it at the time you are getting response from server

dispatch_async(dispatch_get_main_queue(), {

            ViewControllerUtils().hideActivityIndicator(self.view)

            }))

Upvotes: 2

Related Questions