John Pollard
John Pollard

Reputation: 3899

Can you create a method without a callback that calls a method with a callback?

In short, I want to be able to do this

var tasks = API().getTasks();

I want to call a method (like 'getTasks') to

  1. return a value if set OR
  2. make an API call to get the value.

Is there a way to do that by editing the following getTasks method?

Right now I have to send a block to the method "API().getTasks(){ (tasks, error) -> () in }"

func getTasks(callback: (tasks: Dictionary<Int, Task>, error: String?) -> ()) {
    if (tasks.length != 0){
        callback(tasks);
    }else{
      self.httpGet("tasks", params : ""){
          (json, error) -> Void in
          if error != nil {
          } else {
            for task in json {
                var t = Task(dict: task);
                tasks.updateValue(t, forKey: t.id)
            }
        }
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            callback(tasks: tasks, error: error);
        })
    }
}

Below is my httpGet method that is responding back with JSON from an API call.

func httpGet(method: String, callback : (Array<Dictionary<String, AnyObject>>, String?) -> Void) {

    var request = NSMutableURLRequest(URL: NSURL(string: "https://www.testing.com/"+method)!)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {(data, response, error) -> Void in
        if error != nil {
            var nothing : Array<Dictionary<String, AnyObject>> = []
            callback(nothing, error.localizedDescription)
        } else {
            var result = NSString(data: data, encoding:NSASCIIStringEncoding)!
            var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as Array<Dictionary<String, AnyObject>>;
            callback(json, nil)
        }
    }
    task.resume()
}

Upvotes: 0

Views: 154

Answers (1)

tng
tng

Reputation: 4346

If you don't want to pass a closure to getTasks(), how will getTasks() know which function to call in case it needs to?

There are generally a couple approaches:

  1. getTasks() is an instance method of a class. You can provide an appropriate init method for the class that takes a closure and saves it, and in your getTasks(), you can call the saved closure
  2. getTasks() is an instance method of a class that defines a base method that getTasks() calls. You can inherit from this class and override the base method to customize the actions performed.
  3. It appears, though I cannot confirm without looking at more of your code, that getTasks() is a "class method". In this case, you have less options for customization. I don't recommend this option, but a possibility is to have some global/class property that getTasks() can check.

Option 1 is typically preferred by functional programmers; option 2 is typically preferred by OOP programmers. Option 3 is less preferred, but I have seen code like this and it's very hard to maintain. You see it often in languages like C, but even in C, there are better ways to deal with this.

I'm curious too why you don't like the approach you asked about - in fact, that's a very common approach that I think fits well in most functional programming patterns. Is there something about it you don't like?

Upvotes: 1

Related Questions