Engineeroholic Engineeroholic - 6 months ago 33
Swift Question

swift 2 how to use variable outside the function?

I have a class ApiManager() that make request to JSON data in which I learned from this tutorial, which used protocol delegate approach to pass the data to ViewController class

The data is acquired fine but I am not sure how to use it around?! in this case I am trying to use it inside TableView

class ViewController: UITableViewController, ApiManagerDelegate{

var names:[String] = [] // the variable which will hold the JSON data

override func viewDidLoad() {
super.viewDidLoad()

//instantiate the ApiManager Class
//Set the ViewController as its delegate
//perform request to Restaurants info

let manager = ApiManager()
manager.delegate = self
manager.getRestaurantsData()

func didReceiveResponse (info: [String : AnyObject]){

//Read name property from data dictionary (JSON)

if let restaurantsData = info["restaurants"] as? [[String: AnyObject]]{

for restaurant in restaurantsData{
let name = restaurant["name"] as? String
self.names.append(name!)
}
}


print("Data1: \(names)") // prints the data perfectly

}

func didFailToReceiveResponse() {
print("There was an error in recieving API data")
}

}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print (names) //no data here
return names.count //not working
}


I am a bit confused how to work around this, I tried to make return value to didReieveResponse(), but the issue is when I call the function it needs the argument (which is passed to it in the Delegator class "dictionary").. I am completely confused.

Here is the delegator class and protocol for reference:

import UIKit

//Custom Protocol Declaration
@objc protocol ApiManagerDelegate {
optional func didReceiveResponse(info: [ String : AnyObject ])
optional func didFailToReceiveResponse()
}


class ApiManager: NSObject, NSURLSessionDelegate {

//open restaurant web API
private let requestURL = NSURL(string:"http://some-url-here.com")

var delegate: ApiManagerDelegate?

override init() {

super.init()

}

func getRestaurantsData() {

let defaultConfigObject = NSURLSessionConfiguration.defaultSessionConfiguration()

let defaultSession = NSURLSession (configuration: defaultConfigObject, delegate: self, delegateQueue: NSOperationQueue.mainQueue ())

let request = NSMutableURLRequest(URL: requestURL!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 60 )



request.HTTPMethod = "POST"
request.setValue( "application/x-www-form-urlencoded" , forHTTPHeaderField: "Content-Type" )

let dataTask = defaultSession.dataTaskWithRequest(request, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) in

if let responseError = error {

self.delegate?.didFailToReceiveResponse?()
print("Reponse Error: \( responseError )" )

} else {
do {
let dictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! [String: AnyObject]

self.delegate?.didReceiveResponse?(dictionary)
//print( "Response: \( dictionary )" )
print("Response: Success")

} catch let jsonError as NSError {
// Handle parsing error
self.delegate?.didFailToReceiveResponse?()
print( "JSONError: \(jsonError.localizedDescription)")
}
}
})

dataTask.resume()
}


}

thanks,




Update:



For future Developers who might suffer like me, the solution is to use TableViewName.reloadData() as mentioned below..
But please notice, it did only worked with me when I placed DidRecieveResponse() function outside ViewDidLoad, not sure why Hopefully one of the experts can explain it later.

Enjoy!

Answer

do like

 class ViewController: UITableViewController, ApiManagerDelegate{

var names:[String] = []  
 let manager = ApiManager()


 override func viewDidLoad() {
    super.viewDidLoad()

    manager.delegate = self
    manager.getRestaurantsData()
 }

   func didReceiveResponse (info: [String : AnyObject]){

        //Read name property from data dictionary (JSON)

        if let restaurantsData = info["restaurants"] as? [[String: AnyObject]]{

            for restaurant in restaurantsData{
                let name = restaurant["name"] as? String
                self.names.append(name!)
            }

                print("Data1: \(names)") // prints the data perfectly
             if (self.names.count>0)
             { 
              yourtableview.reloadData()
             }
        }

    }


  func didFailToReceiveResponse() {
    print("There was an error in recieving API data")
}
Comments