MatterGoal
MatterGoal

Reputation: 16430

Capture List and Function passed as argument in swift

I have a function with this prototype:

func myFunction(completionHandler:((response:[NSString:AnyObject])->Void)?))

The completionHandler prototype can be passed as closure or as a function... passing it as closure I know how to define a capture list with this syntax [weak self], but how can I define a capture list if instead of defining the closure directly in the function argument I want to pass a function name?

myFunction(anotherFunction) // how to set capture list from here?

VS

myFunction{ 
     [weak self] (response) in

}

```

EDIT-----

A possible solution is to wrap the function code into a block, set the capture list and execute the block... but it sounds so strange :/

myFunction(anotherFunction) // how to set capture list from here?
.
.
.
func anotherFunction(response:[NSString:AnyObject]) { 
    let safeBlock = { 
       [weak self] in { 
         self?.callSomethingSafely()
       }
    }

    safeBlock()
}

Upvotes: 9

Views: 1452

Answers (2)

Jay Patel
Jay Patel

Reputation: 46

@MatterGoal your solution will still produce a reference cycle.

I am assuming you are aware of the situations where we should use a capture list. For a scenario like myFunction(anotherFunction), we cannot define a capture list for a method (func) named anotherFunction itself. At least for now, lets hope in future we can.

We can only define a capture for a closure. A method can act as a closure with same signature but it (method) does not support capture list for itself.

Solutions:

  1. Make a lazy var anotherFunction = { } in which we can define capture list.
  2. Make your function return a closure:

    func anotherFunction() -> (() -> Void) {
        return { [weak self] in
            // do anything you want with self? properties or methods.
            // this won't create a strong reference cycle
        }
    }
    

Upvotes: 1

Daniel Hall
Daniel Hall

Reputation: 13679

EDIT (based on correction from Hamish below):

I'm not aware of a way to force a referenced method to internally use a weak version of a captured variable. As you have in your example, it's up to to the actual method implementation to do that or not.

However, it's worth noting that unless you are going to be storing a reference to that completion handler indefinitely, you don't need to worry about weak self.

I assume that completion handler will be called as soon as some asynchronous task that myFunction kicks off is completed. In that case, any references captured by the completion handler will only be held until the completion handler runs. Then those references will be released and there won't be any retain cycles. Weak self in closures in only important if "self" retains the closure and the closure captures "self", setting up a circular reference / retain cycle.

Upvotes: 3

Related Questions