bnassler bnassler - 5 months ago 27
Swift Question

Swift iOS Best Practise REST Callback

My Swift iOS App communicates with a REST Webservice to retrieve JSON data.
Upon completion, it will refresh a UITableView using the respective UITableViewController.

In order to keep this clean, I created a new swift file and put the request code there.

Interface.swift



import Foundation
class WTInterface {

func login() -> Bool {
var token: String?
println("login. initializing request...")
var url = NSURL(string: "https://report.somewebservice/data.cgi")
var request = NSMutableURLRequest(URL: url!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params = [:]

var requestBody = [
"method" : "login",
"params" : [
"customerId": "235879840188032",
"login": "foobar",
"pass": "somepassowrd",
"language": "en"
],
"version" : "1.1"
]
var err: NSError?
request.HTTPBody = NSJSONSeri...............


ViewController



import UIKit

class ViewController: UIViewController {


override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.


var wtinterface = WTInterface()


wtinterface.login()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}


The question is how to best refresh my UITableView, since this is an asynchronous request.
I have read a lot about callbacks and closures and older blog posts and answers, but I didn't find a good answer for this. (Mostly because I believe the strategies are outdated by now...)

Can anyone point me in the right direction and paste some sample code?

Answer Source

Maybe useful for someone a little bit of time down the road:

The answer is using a closure. Note that the @escaping indicates that the closure is escaping i.e. it does not "just run through" but may for example wait for something asynchronous like a network request. Note that when using those, the UI cannot be updates within these (since they are not running on the mean thread) instead schedule something on the main thread for that.

func myClosure(callback: @escaping (_ greeting: String?) -> Void) {
  print("lalalala")
  // Do async request stuff here
  callback("Hi there!")
}

myClosure() { aGreeting in
  guard aGreeting != nil else {
    return
  }
  print(aGreeting!)
}