Anonymous Closure Argument Not Contained in a Closure

Swift map on UILabel Anonymous closure argument not contained in closure

This code is invalid because it's using an anonymous closure argument $0, without being in a closure.

[nameLabel, numberLabel, informationLabel].map(contentView.addSubview($0))

There are two ways to fix this, either put it in a closure:

[nameLabel, numberLabel, informationLabel].map { contentView.addSubview($0) }

Or better yet, just use the instance method directly:

[nameLabel, numberLabel, informationLabel].map(contentView.addSubview)

In either case, you should use forEach rather than map, since you don't care about the (Void) return value of addSubview:

 [nameLabel, numberLabel, informationLabel].forEach(contentView.addSubview)

(lldb) error: anonymous closure argument not contained in a closure

The "p" command actually compiles the text you type as though the expression had been in the text of the frame you are stopped in. To do that it has to completely recreate that context. lldb gets a lot of this right, but it doesn't yet know how emulate the $ closure automatic variables in the context it uses to compile expressions.

But more generally, the job print tries to do is a much harder task that just viewing local variables, and not surprisingly lldb also has a more straightforward way to view simple local variables. That facility is what Xcode uses to implement the locals view and the tooltips. But it is also an lldb command-line command:

(lldb) frame var $0

The "frame var" command doesn't have a full language parser, for instance it can't evaluate expressions. But it does allow you to specify elements of a struct, for instance:

(lldb) frame var $0.delegate

You might have more luck with the frame var command.

how to call a closure with argument in a function

That is not how closures work in Swift. And the code you wrote doesn't even make sense. Why do you assign n to name then change the value of name just to print it ?

The function with the closure will call the closure with a given value. You can think of closures as lambda functions. Here is an example:

func test(_ closure: @escaping (String) -> Void) {
closure("My string")
}

test { str in
print(str) //prints " My string"
}

For what you are trying to achieve, just use a String parameter in your function:

func test(_ str: String) {
print(str)
}

test("My string") // prints "My string"

Or use a closure that takes Void:

func test(_ closure: @escaping (Void) -> Void) {
closure()
}

test {
print("My string") // prints "My string"
}

Anonymous closure can not be used inside a closure that has explicit arguments

There are two ways to write closures: with explicit argument names, or by referring to the arguments as $0, $1 etc.

For example, these two things are equivalent:

// implicit argument names, $0 and $1
let x = reduce(1...5, 0) { $0 + $1 }

// explicit argument names i and j
let y = reduce(1...5, 0) { i, j in i + j }

But you can’t mix these things – either you name the arguments, or you use $n. You can’t do both:

// name the arguments, but still use $0 and $1
let x = reduce(1...5, 0) { $0 + $1 }
// compiler error: Anonymous closure arguments cannot be used
// inside a closure that has explicit arguments

In your example, it looks like you’ve forgotten to supply a closure to the filter method. This means your $0 isn’t inside a new closure without arguments – so the Swift compiler thinks your $0 is referring to the outer closure that names it’s arguments explicitly as records and error. So it’s complaining you can’t refer to arguments as $0 inside a closure with explicit argument names.

(the fix is of course to actually supply a closure to filter i.e. replace your () with {})

Print (po) the value of a Swift anonymous closure argument from the console in Xcode

This is a known issue with Xcode 8.1 GM Seed. From the release notes:

Anonymous closure arguments in Swift cannot be used in LLDB expressions. For example, po $0 is not supported.

You can use the frame variable command to print its value:

fr va $0

This issue is filed as rdar://28611943.

Accessing only a subset of anonymous closure arguments

To the compiler, it looks like your closure is only handling a single float parameter, because your closure never references the other 5 "things" in any way. So there is an apparent mismatch and the compiler flags it as an error.

If you reference all 6 input parameters in any valid way, the error will disappear. For example, although this is not something you should ever write, merely referencing the additional parameters like this will be valid:

self.someClosure = { self.handleThing0($0); _ = [$1,$2,$3,$4,$5] }

The shortest / best possible way to express what you are going for is:

self.someClosure = { thing0, _, _, _, _, _ in self.handleThing0(thing0) }

where each _ represents a value you are ignoring, but the compiler can infer that they would be Float values.



Related Topics



Leave a reply



Submit