Ehab Saifan
Ehab Saifan

Reputation: 310

Swift closures with delegates

So I am trying to create a closure when I receive something from a delegate method:

typealias CompletionResponse = ((_ response: AnyObject) -> Void)?

class SomeClass {

    static let shared = SomeClass()

    var completion: CompletionResponse?

    func getSomthing(completion: CompletionResponse) {
        self.completion = completion
    }

    func someDelegateMethode(info: [String]) {
        // Error is here
        if let completion = self.completion {
            completion(info)
        }
    }
}

 _ = SomeClass.shared

SomeClass.shared

SomeClass.shared.getSomthing { (obj) in
    print(obj as! [String])
}

SomeClass.shared.someDelegateMethod(info: ["Hello", "There"])

I am not sure how to do that.. I appreciate any help.

Error received :
Cannot call value of non-function type 'CompletionResponse' (aka 'Optional<(AnyObject) -> ()>')

Thanks

Upvotes: 2

Views: 538

Answers (2)

Samah
Samah

Reputation: 1234

Remove the optional from the typealias. The compiler doesn't understand how to call completion since it has a double optional type.

Additionally, you can use optional chaining rather than an if let.

self.completion?(info)

Upvotes: 5

Yannick
Yannick

Reputation: 3278

Your typealias CompletionResponse is Optional and your completion attribute is also Optional. When you print the type of completion, you can see that it is a double Optional:

print(type(of: self.completion)) //Optional<Optional<(AnyObject) -> ()>> 

What you want to do is call your completion function. However, since it is wrapped inside an Optional, you're telling the compiler to call a function on your enum Optional. Enums are not function-types and cannot be called and that is what the error is trying to tell you.

Now, there are multiple ways to solve your problem.

  1. The solution that makes the most sense to me is remove the Optional type from your typealias CompletionResponse.

    typealias CompletionResponse = (_ response: AnyObject) -> Void

    if let completion = self.completion { completion(info as AnyObject) }

    or as a one-liner self.completion?(info as AnyObject)

  2. You can also keep the double Optional and unwrap using if let

    if let completion = self.completion.flatMap({ $0 }) { completion(info as AnyObject) }

    or as a one-liner self.completion??(info as AnyObject)

Note that you have to specify info as AnyObject, otherwise you get another compiler error.

Upvotes: 1

Related Questions