How? function as param with a default??

I'm trying to use a function as a parameter in (duh) another function.

The param function is a callback.

I've got another function in the same class which matches the required format:

I want to use deadCallback as a default for the param so the function myFunc doesn't *require* a callback param.


If I leave the code: = self.deadCallback out the app compiles with no problem.

If I include it I get a compile time error:
"value of type (myClass) -> () -> (myClass) has no member deadCallback"


What am I doing wrong?
Can I do this?
If so, how?


class myClass {

func myFunc(_ url: String, callback: @escaping (_ resp: String) -> () = self.deadCallback) {

//do something that might make a string

var myStr? = "blah blah blah" //this may be nil which is perfectly acceptable

if(myStr != nil) {

callback(myStr!)

}

}

func deadCallback(_ resp: String) {

return

}


}

Replies

Just make the callback closure optional.


In the example below, line 3 has an optional closure in the form of ((_ resp: String) -> Void)?, with the default value of nil. Line 7 uses callback?(myStr) to perform the callback only if it's non-nil.


class MyClass {

    func myFunc(_ url: String, callback: ((_ resp: String) -> Void)? = nil) {
        //do something that might make a string
        var myStr: String? = "blah blah blah" //this may be nil which is perfectly acceptable
        if let myStr = myStr {
            callback?(myStr)
        }
    }

}

What version of Xcode are you using? My Xcode 9.4.1 shows use of unresolved identifier 'self'. (With fixing `var myStr?` to `var myStr: String?`.)


What am I doing wrong?


Default parameters for functions are evaluated from the caller's side, so you cannot use any sort of things which are available in the callee's context. You cannot use `self`.


Can I do this?
If so, how?


TheCD's proposal is a very good alternative, or you can use a closure literal.


    func myFunc(_ url: String, callback: @escaping (_ resp: String) -> () = {_ in}) {
        //do something that might make a string
        var myStr: String? = "blah blah blah" //this may be nil which is perfectly acceptable
        if let myStr = myStr {
            callback(myStr)
        }
    }

This works in a playground...



class MyClass {

  typealias MyCallbacks = (_ resp: String) -> ()

  static let deadCallback:MyCallbacks = {
       message in
       print("Called deadCallback with \"\(message)\"")
  }

  func myFunc(_ url: String, callback: @escaping MyCallbacks = MyClass.deadCallback) {
       //do something that might make a string
       let myStr:String? = "blah blah blah" //this may be nil which is perfectly acceptable
       if let s = myStr {
           callback(s)
       }
  }
}


let test = MyClass()
test.myFunc("http://somewhere.com")


let testCallback:MyClass.MyCallbacks = {
  message in
  print("Called testCallback with \"\(message)\"")
}

test.myFunc("http://somewhere.com",callback:testCallback)

Yes, that does work. However, in this situation, I prefer optional closures for the following reasons:


1. "Dead callbacks" add more code to compile and maintain

2. Optional closures seem to be the convention used in system frameworks.