-4

I am just trying to get some information from a request using completionHandler. The thing is that I need the array with all the information from other part of the code and it seems I can't access to it. Here it is where I access to the data:

private func loadUserData(completionHandler: @escaping ([String]) -> ()) {
    // We're getting user info data from JSON response
    let session = Twitter.sharedInstance().sessionStore.session()
    let client = TWTRAPIClient.withCurrentUser()
    let userInfoURL = "https://api.twitter.com/1.1/users/show.json"
    let params = ["user_id": session?.userID]
    var clientError : NSError?
    let request = client.urlRequest(withMethod: "GET", url: userInfoURL, parameters: params, error: &clientError)
    client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
        if connectionError != nil {
            print("Error: \(connectionError)")
        }
        
        do {
            let json = JSON(data: data!)
            if let userName = json["name"].string,
                let description = json["description"].string,
                let followersCount = json["followers_count"].int,
                let favouritesCount = json["favourites_count"].int,
                let followingCount = json["friends_count"].int,
                let lang = json["lang"].string,
                let nickname = json["screen_name"].string {
                
                    self.userData.append(userName)
                    self.userData.append(description)
                    self.userData.append(String(followersCount))
                    self.userData.append(String(favouritesCount))
                    self.userData.append(String(followingCount))
                    self.userData.append(lang)
                    self.userData.append(nickname)
                
                    completionHandler(self.userData)
            }
        }
    }
}

func manageUserData(index: Int) {
    loadUserData() {_ in 
        return self.userData[index]
    }
}

And here it is where I need that data to show it:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let rowNumber = indexPath.row
    let cellIdentifier = "TableViewCell"
    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? TableViewCellController else {
        fatalError("The dequeued cell is not an instance of TableViewCellController.")
    }
    
    switch rowNumber {
        case 0:
            cell.titlePlaceholder.text = "Name:"
            cell.valuePlaceholder.text = manageUserData(index: 1)

In this last line it's where the error occurs: "Cannot assign value of type '()' to type String?. I am not sure if I am using completionHandler properly in order to retrieve the data and ensure I can access to it from different parts of the code.

Any idea ? Thank you very much!

UPDATE I was not using completionHandler properly. So I changed it by :

private func loadUserData(completion: @escaping (_ myArray: [String]) -> Void)

So my manageUserData function now looks like this:

func manageUserData() {
    loadUserData {
        (result: [String]) in
        self.secondUserData = result
    }
}

Hope this helps!

Waldi
  • 39,242
  • 6
  • 30
  • 78
TibiaZ
  • 730
  • 1
  • 8
  • 21
  • Unclear what you expect. Your `func manageUserData(index: Int)` does not return any value. Thus you cannot "assign" it to a label's `text`; it isn't text. It isn't a String. It's a Void (no value). – matt Jul 25 '17 at 17:32

1 Answers1

1

Since this is async network call, you should start this call in your VC's viewWillAppear, viewDidAppear, or viewDidLoad -- depending on if you need the data to reload.

override func viewWillAppear(_ animate: Bool) {
    super.viewWillAppear(animate)
    sessionManager.loadUserData { (strings) in

    }
}

then inside of your loadUserData closure that will be ran whenever the call is complete, load the data into an array used as the tableView's datasource and call tableView.reloadData()

sessionManager.loadUserData { (strings) in 
    self.dataSource = strings
    self.tableView.reloadData()
}

Then for your cellForRow you would just need:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let rowNumber = indexPath.row
    let cellIdentifier = "TableViewCell"
    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? TableViewCellController else {
        fatalError("The dequeued cell is not an instance of TableViewCellController.")
    }

    switch rowNumber {
        case 0:
            cell.titlePlaceholder.text = "Name:"
            cell.valuePlaceholder.text = dataSource[0]
    }
}

make sure your numberOfRows is returning dataSource.count

Jacob Boyd
  • 672
  • 3
  • 19