I would like to call an #autoclosure parameter inside dispatch_async block.
func myFunc(#autoclosure condition: () -> Bool) {
dispatch_async(dispatch_get_main_queue()) {
if condition() {
println("Condition is true")
}
}
}
I get the following error.
Closure use of #noescape parameter may allow it to escape.
Is it possible to call #autoclosure parameter asynchronously?
Tested in Xcode 6.4 (6E23).
Yes, so long as you declare them #autoclosure(escaping):
Declarations with the autoclosure attribute imply noescape as well, except when passed the optional attribute escaping.
So this should do it:
func myFunc(#autoclosure(escaping) condition: () -> Bool) {
dispatch_async(dispatch_get_main_queue()) {
if condition() {
println("Condition is true")
}
}
}
Updating the answer from Airspeed Velocity, you can pass weak self directly into escaping autoclosure.
var boolValue: Bool = true
func myFunc(condition: #autoclosure #escaping () -> Bool?) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
if let condition = condition() {
print("Condition is \(condition ? "true" : "false")")
}
}
}
func main() {
weak var weakSelf = self
myFunc(condition: weakSelf?.boolValue)
}
Related
I'm looking for a way to nullify an escaping closure without calling it.
func should(completion: #escaping () -> Void) {
if something {
completion = nil
} else {
completion()
}
}
As long as I understand, the escaping closure can be called after the should function is finished, it will alive until it is get called.
Is there a way to nullify the closure(and captured values) without calling it?
In your example, the closure is in fact not escaping, since you're not assigning it to anything outside the function, so there's no need to nullify:
func should(completion: () -> Void) {
if !something {
completion()
}
}
But if it was escaping, say by assigning it to a property, then you could nullify the property to release it:
class Foo {
let fn: (() -> Void)?
func should(completion: #escaping () -> Void) {
fn = completion
}
func executeAndRelease() {
fn?()
fn = nil
}
}
If you have a sync function, how would you convert it to an async function?
func syncFunc() -> Int {
//Do something
}
Would this work?
func asyncFunc(_ syncFunc:()->Int, _ completion:(Int)->()) -> Int {
DispatchQueue.background.async{
completion( syncFunc() )
}
}
No, functions containing an asynchronous task cannot return any value from the closure body and both closures must be marked as #escaping
func asyncFunc(_ syncFunc: #escaping ()->Int, completion: #escaping (Int)->()) {
DispatchQueue.global().async {
completion( syncFunc() )
}
}
I have a function with a completion handler, returning one parameter or more.
In a client, when executing a completion handler, I'd like to have an unowned reference to self, as well as having access to the parameter passed.
Here is the Playground example illustrating the issue and the goal I'm trying to achieve.
import UIKit
struct Struct {
func function(completion: (String) -> ()) {
completion("Boom!")
}
func noArgumentsFunction(completion: () -> Void) {
completion()
}
}
class Class2 {
func execute() {
Struct().noArgumentsFunction { [unowned self] in
//...
}
Struct().function { (string) in // Need [unowned self] here
//...
}
}
}
As I said in my comment
Struct().function { [unowned self] (string) in
//your code here
}
Capture list and closure parameters that should be the order in closures more info from Apple Documentation
Defining a Capture List
Each item in a capture list is a pairing of
the weak or unowned keyword with a reference to a class instance (such
as self) or a variable initialized with some value (such as delegate =
self.delegate!). These pairings are written within a pair of square
braces, separated by commas.
Place the capture list before a closure’s parameter list and return
type if they are provided:
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// closure body goes here
}
If a closure does not specify a parameter list or return type because
they can be inferred from
context, place the capture list at the very start of the closure,
followed by the in keyword:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
Is it just the syntax for including [unowned self] in the closure parameter list you need?
struct Struct {
func function(completion:(String)->()) {
completion("Boom!")
}
}
class Class {
func execute() {
Struct().function { [unowned self] string in
print(string)
print(self)
}
}
}
Class().execute()
I am trying to use a function within a closure but I am receiving an error 'cannot convert value of type () to closure result type Bool'. The following code demonstrates the error. How can I make this work?
func test1(){
test2(){ success in
self.test1()
}
}
func test2(completionHandler: (Bool) -> Bool){
completionHandler(true)
}
You specify that the test2 closure returns a Bool, so return one:
func test1(){
test2 { (success) -> Bool in
test1()
return success
}
}
Have test2's closure return void if you don't want to return a value from it:
func test1(){
test2 { (success) in
test1()
}
}
func test2(completionHandler: (Bool) -> Void){
completionHandler(true)
}
With closures I usually append [weak self] onto my capture list and then do a null check on self:
func myInstanceMethod()
{
let myClosure =
{
[weak self] (result : Bool) in
if let this = self
{
this.anotherInstanceMethod()
}
}
functionExpectingClosure(myClosure)
}
How do I perform the null check on self if I'm using a nested function in lieu of a closure (or is the check even necessary...or is it even good practice to use a nested function like this) i.e.
func myInstanceMethod()
{
func nestedFunction(result : Bool)
{
anotherInstanceMethod()
}
functionExpectingClosure(nestedFunction)
}
Unfortunately, only Closures have "Capture List" feature like [weak self]. For nested functions, You have to use normal weak or unowned variables.
func myInstanceMethod() {
weak var _self = self
func nestedFunction(result : Bool) {
_self?.anotherInstanceMethod()
}
functionExpectingClosure(nestedFunction)
}
Does not seem to be the case anymore. This is valid in swift 4.1:
class Foo {
var increment = 0
func bar() {
func method1() {
DispatchQueue.main.async(execute: {
method2()
})
}
func method2() {
otherMethod()
increment += 1
}
method1()
}
func otherMethod() {
}
}
The question remains: How is self captured ?