user149533
user149533

Reputation:

Capturing a property of an object for a closure in Swift

I'm rewriting some code to append jobs to an array of closures rather than execute them directly:

var someObject: SomeType?
var jobsArray: [() -> ()] = []

// before rewriting
doExpensiveOperation(someObject!.property)

// 1st attempt at rewriting
jobsArray.append {
    doExpensiveOperation(someObject!.property)
}

However, because the value of someObject might change before the closure is executed, I'm now adding a closure list as follows:

// 2nd attempt at rewriting
jobsArray.append { [someObject] in
    doExpensiveOperation(someObject!.property)
}

Hopefully then if, say, someObject is subsequently set to nil before the closure executes, the closure will still access the intended instance.

But what's the neatest way to deal with the possibility that the value of .property might change before the closure is executed? Is there a better way than this?

// 3rd attempt at rewriting
let p = someObject!.property
jobsArray.append { 
    doExpensiveOperation(p)
}

I'm not very keen on this solution because it means changing the original line of code. I'd prefer this but it doesn't work:

// 4th attempt at rewriting
jobsArray.append { [someObject!.property] in
    doExpensiveOperation(someObject!.property)
}

Pretty new to Swift, so all guidance gratefully received. Thanks!

Upvotes: 1

Views: 613

Answers (1)

Hamish
Hamish

Reputation: 80801

A capture list such as [someObject] is actually syntactic sugar for [someObject = someObject], where the right hand side can be an arbitrary expression that gets bound to a new constant upon the closure being formed.

Therefore one option is to write your example as:

jobsArray.append { [property = someObject!.property] in
  doExpensiveOperation(property)
}

Upvotes: 2

Related Questions