Swift optional chaining doesn't work in closure - ios

My code looks like this. My class has an optional var
var currentBottle : BottleLayer?
BottleLayer has a method jiggle().
This code, using optional chaining, compiles fine in my class:
self.currentBottle?.jiggle()
Now I want to construct a closure that uses that same code:
let clos = {() -> () in self.currentBottle?.jiggle()}
But I get a compile error:
Could not find member 'jiggle'
As a workaround I can force unwrapping
let clos = {() -> () in self.currentBottle!.jiggle()}
or of course I can use full-fledged optional binding, but I'd rather not. I do recognize that optional chaining is just syntactical sugar, but it is hard to see why this syntactical sugar would stop working just because it's in a handler (though there may, of course, be a reason - but it's a surprise in any case).
Perhaps someone else has banged into this and has thoughts about it? Thanks.

This is NOT a bug. It's simply your closure type which is wrong.
The correct type should return an optional Void to reflect the optional chaining:
let clos = { ()->()? in currentBottle?.jiggle() }
The problem in details:
You declare your closure as a closure that returns Void (namely ->()).
But, do remember that, as like every time you use optional chaining, the return type of the whole expression is of optional type. Because your closure can either return Void if currentBottle do exists… or nil if it doesn't!
So the correct syntax is to make your closure return a Void? (or ()?) instead of a simple Void
class BottleLayer {
func jiggle() { println("Jiggle Jiggle") }
}
var currentBottle: BottleLayer?
currentBottle?.jiggle() // OK
let clos = { Void->Void? in currentBottle?.jiggle() } // Also OK
let clos = { () -> ()? in currentBottle?.jiggle() } // Still OK (Void and () are synonyms)
Note: if you had let Swift infer the correct type for you instead of explicitly forcing it, it would have fixed the issue for you:
// Even better: type automatically inferred as ()->()? — also known as Void->Void?
let clos = { currentBottle?.jiggle() }
[EDIT]
Additional trick: directly assign the optional chaining to a variable
You can even assign the function directly to a variable, like so:
let clos2 = currentBottle?.jiggle // no parenthesis, we don't want to call the function, just refer to it
Note that the type of clos2 (which is not explicitly specified here and is thus inferred automatically by Swift) in this case is not Void->Void? — namely a function that returns either nil or Void) as in the previous case — but is (Void->Void)?, which is the type for "an optional function of type Void->Void".
This means that clos2 itself is "either nil or is a function returning Void". To use it, you could once again use optional chaining, simply like that:
clos2?()
This will evaluate to nil and do nothing if clos2 is itself nil (likely because currentBottle is itself nil)… and execute the closure — thus the currentBottle!.jiggle() code — and return Void if clos2 is non-nil (likely because currentBottle itself is non-nil).
The return type of clos2?() itself is indeed Void?, as it returns either nil or Void.
Doing the distinction between Void and Void? may seem pointless (after all, the jiggle function does not return anything in either case), but it let you do powerful stuff like testing the Void? in an if statement to check if the call actually did happen (and returned Void namely nothing) or didn't happen (and return nil):
if clos2?() { println("The jiggle function got called after all!") }
[EDIT2] As you (#matt) pointed out yourself, this other alternative has one other major difference: it evaluates currentBottle?.jiggle at the time that expression got affected to clos2. So if currentBottle is nil at that time, clos2 will be nil… even if currentBottle got a non-nil value later.
Conversely, clos is affected to the closure itself, and the optional chaining is only evaluated each time clos is called, so it will evaluate to nil if currentBottle is nil… but will be evaluated to non-nil and will call jiggle() if we call clos() at a later time at which point currentBottle became non-nil.

let closure = { () -> () in
self.currentBottle?.jiggle()
return
}
Otherwise the compiler thinks the result of that statement should be returned from the closure and it realizes there is a mismatch between () (return type) and the optional returned by the statement (Optional<Void>). By adding an explicit return, the compiler will know that we don't want to return anything.
The error message is wrong, of course.

Okay, another approach. This is because closures in Swift have Implicit Returns from Single-Expression Closures. Because of the optional chain, your closure has a return type of Void?, so:
let clos = {() -> Void? in self.currentBottle?.jiggle()}

Letting the closure type be inferred seems to work as well.
let clos2 = { currentBottle?.jiggle() }
clos2() // does a jiggle
But I'm pretty sure this is just the compiler assigning a type of () -> ()?

Related

confused with the functionality of `return` in swift

I am confused with return in Swift. I understand it's used to return the value in a function, if used like this:
func double(value: int) -> Int {
return value * 2
}
But I often just see return being used, like in a guard statement in an optional binding like this:
guard let value = value else (
print ("nothing")
return
}
So what is the purpose of having just return in the guard statement like this? Actually, I often see this not only in guard statements when unwrapping optional values. I always find this problem when writing code, when I want to use an optional string from a dictionary.
let info = ["name": "sarah", "hometown": "sydney"]
class UserInfo {
func getTheName() -> String {
guard let name = info["name"] else { return }
return name
}
}
// Compile time error: "Non-void function should return a value"
I get this error even though I have written return name. Xcode still complains that I have not returned a value. Is it because of the return in the guard statement?
So, could you please tell me the purpose of return in Swift? It is confusing for me.
return without any argument returns Void. This form of the return statement can only be used with a function that returns Void.
Once the return statement executes, the function exits and no more code in your function executes. Since you have a return in the guard statement, the second return name won't be executed (it couldn't anyway since it wouldn't have a name to return), which is why you get a compiler error; the compiler looks at all of the paths that your function could take to return something and ensures that all of those paths return what the function signature says it will.
The function in your question states that it returns a String, so you can't simply say return in the guard statement as that returns Void, violating the contract expressed by your function signature.
You could return a default value that isn't Void:
func getTheName () -> String {
guard let name = info["name"] else {
return ""
}
return name
}
This could be written much more succinctly using the nil-coalescing operator; return info["name"] ?? ""
You can also use return in a function that returns Void (or has no explicit return type, in which case it is implicitly understood to return Void)
So you could have a function like:
func maybePrint(theMessage: String?) -> Void {
guard let msg = theMessage else {
return
}
print(msg)
}
You're on the right track.
In your guard statement inside getTheName(), the 'return' keyword will try to exit the function itself if the guard fails. But the function requires you to return a String and as such you get the compiler error.
Here is a portion of another SO answer to a similar question:
guard forces you to exit the scope using a control transfer statement.
There are 4 available to you:
return and throw both exit the function/method continue can be used
within loops (while/for/repeat-while) break can be used in loops
(while/for/repeat-while) to exit the immediate scope. Specifying a
label to break to will allow you to exit multiple scopes at once (e.g.
breaking out of nested loop structure). When using a label, break can
also be used in if scopes. Additionally, you may exit the scope by
calling a function that returns Never, such as fatalError.
Stack Overflow: If the Swift 'guard' statement must exit scope, what is the definition of scope?

Closures In Swift?

I am new to iOS coding and I am stuck in closures feature of SWIFT. I have referred to many tutorials and found that closures are self written codes which can be used in many ways eg. as arguments in function call,parameters in function definition,variables. I am giving below an example below with my associated thoughts about the code & questions. Please help me if I am wrong in my understanding. I know I am wrong at many points,so please rectify me.
1.1st Part
func TEST(text1:String,text2:String,flag: (S1:String,S2:String)->Bool)//In this line,I think,I am using flag is a closure which is passed as parameter in a function. And if so why doesn't it follow the standard closure syntax?
{
if flag(S1: text1, S2: text2) == true//I want to check the return type what flag closure gets when it compares the both string during function call. Why can't I write as if flag == true as flag is the name of the closure and ultimately refers to the return type of the closure?
{
print("they are equal")
}
else
{
//
}
}
2nd Part
This part is the most troublesome part that really confuses me when I am calling the function. Here I am also using the same closure. What is happening over here? How is the closure being used? Is it capturing values or something else?
TEST("heyy", text2: "heyy") { (S1, S2) -> Bool in
S1==S2
}
Thanks for your kind consideration.
Your closure usage is ok. A closure is some code that can be passed to be executed somewhere else. In your case you can choose to pass the real test you want to the function TEST, simple string test or case-insensitive test, etc. This is one of the first usage of closure: obtain more genericity.
And yes closures capture something, it captures some part of the environnement, i.e. the context in which they are defined. Look:
var m = "foo"
func test(text1:String, text2:String, testtFunc: (s1:String, s2:String) -> Bool) {
m = "bar"
if testFunc(s1: text1, s2: text2) { print("the test is true") }
}
m = "baz"
test("heyy", text2: "heyy") { (s1, s2) -> Bool in
Swift.print("Value for m is \(m)")
return s1==s2
}
The closure captures m (a variable that is defined in the context in which you define the closure), this means that this will print bar because at the time the closure is executed, the captured m equals to bar. Comment bar-line and baz will be printed; comment baz-line and foo will be printed. The closure captures m, not its value, m by itself, and this is evaluated to the correct value when the closure is evaluated.
Your first function works like this :
arguments :
String 1
String 2
a function that takes two Strings as arguments and returns a Bool
body :
execute the function (flag) with text1 and text2 and check the result.
The function doesn't know at all what you are testing, it only knows that two pieces of text are needed and a Bool will be returned.
So this function allows you to create a general way of handling different functions that all have two Strings as input. You can check for equality or if the first pieces of text is a part of the second and so on.
This is useful for many things and not so far from how array filtering / sorting / map works.
2nd Part :
This is just how you call a function with a closure.
TEST("heyy", text2: "heyy") { (S1, S2) -> Bool in
S1 == S2
}
You can also call it like this :
func testStringEqualityFor(text:String, and:String) -> Bool {
return text == and
}
TEST("hey", text2: "hey", flag: testStringEqualityFor)
Instead of using the trailing closure syntax to pass an unnamed function, you now pass a named function as one of the arguments.
It al becomes a lot clearer when you simplify it.
This is a function that takes another function as an argument.
Now we can call/use this function inside it. The argument function takes a bool as it's argument. So we give it a true
func simpleFunctionWithClosure(closure:(success:Bool) -> Void) {
// use the closure
closure(success: true)
}
When we use the function we need to pass it a function. In Swift you have the trailing closure syntax for that, but that is only available (and even then optional) to the first function as argument.
Trailing closure syntax means that instead of passing a named function you can write:
myFunction { arguments-for-closure-as-tuple -> return-for-closure-as-tuple in
function-body
}
The closure will receive an argument of Bool and returns nothing so Void.
In the body we can handle the arguments and do stuff with them.
But it is important to remember that what is inside the closure is not called directly. It is a function declaration that will be executed by simpleFunctionWithClosure
// use the function
simpleFunctionWithClosure { (success) -> Void in
if success {
print("Yeah")
} else {
print("Ow")
}
}
Or with a named function :
func argumentFunction(success:Bool) -> Void {
if success {
print("Yeah")
} else {
print("Ow")
}
}
simpleFunctionWithClosure(argumentFunction)
Compiler wouldn't have any expectation how your closure is for. For example in your first case, it could not estimate the closure's intake parameters is always just reflect to the first and second parameters of the TEST function when we are always able to write the following code :
func Test(str1:String,str2:String,closure:(String,String)->Bool){
if closure(str[str1.startIndex...str1.startIndex.advanced(2)],str2[str2.startIndex.advanced(1)...str2.endIndex])
{ ... }else{ ... }
//Just an example, everybody know no one write their code like this.
}
The second case, I thought you've just overlooked the syntax sugar:
For a trailing closure A->B:
{ a:A -> B in a.bValue() }
is equal to :
{ a:A -> B in return a.bValue() }
Also, I think this TEST function isn't a good example when the task of it can be done without using closure. I think you can write a map function by yourself for a better understand of why and when to use closure.

'?'must be followed by a call, member lookup or subscript

I have defined a String type computed property:
var name : String? {
//an optional variable
var theName : String?
if SOME_CONDITION {
theName = “I have a name”
}
//ERROR: '?'must be followed by a call, member lookup or subscript
return theName?
}
I want to return whatever theName is, if it is nil, return nil. So I use return theName? , I don’t want to have runtime error. The compiler however raise an error '?'must be followed by a call, member lookup or subscript Why? How to get rid of it.
What about this? Looks more elegant to me:
var name : String? {
let condition = true // your own condition here of course
return condition ? "I have a name" : nil
}
The problem in your code:
var name : String? {
var theName : String?
let condition = true // your own condition here of course
if condition {
theName = "I have a name"
}
return theName // get rid of the ? here
}
The field theName is already optional, no need to add another ? there.
Why is my proposed solution not an alternate solution:
The construct I used is called ternary operator:
The ternary conditional operator is a special operator with three parts, which takes the form question ? answer1 : answer2. It is a shortcut for evaluating one of two expressions based on whether question is true or false. If question is true, it evaluates answer1 and returns its value; otherwise, it evaluates answer2 and returns its value.
It behaves like the if statement but is suitable here as it is shorter and thus clearer to read: Depending on the condition, the value is either theName or nil. You really don't need to assign the value to any other variable, because, afterall, you are computing it, so might as well simply return it as the condition decides, what the value is.
Adding ? to the end of a type makes it Optional.
Adding ? to the end of an optional variable invokes Optional Chaining.
You specify optional chaining by placing a question mark (?) after the
optional value on which you wish to call a property, method or
subscript if the optional is non-nil. This is very similar to placing
an exclamation mark (!) after an optional value to force the
unwrapping of its value. The main difference is that optional chaining
fails gracefully when the optional is nil, whereas forced unwrapping
triggers a runtime error when the optional is nil.
To reflect the fact that optional chaining can be called on a nil
value, the result of an optional chaining call is always an optional
value, even if the property, method, or subscript you are querying
returns a non-optional value. You can use this optional return value
to check whether the optional chaining call was successful (the
returned optional contains a value), or did not succeed due to a nil
value in the chain (the returned optional value is nil).
Specifically, the result of an optional chaining call is of the same
type as the expected return value, but wrapped in an optional. A
property that normally returns an Int will return an Int? when
accessed through optional chaining.
Example
class Foo {
var bar: Int
}
var x: Foo? // ? is attached to type Foo, it makes x an optional variable
let y: Int? = x?.bar // ? is attached to the variable x, this is optional chaining, it makes .bar return Int?

Incorrect try/catch behavior in Xcode 7 beta 3's Swift 2?

I have a problem with some Swift 2 code, compiled using Xcode 7 beta 3.
I have a class (see below) that has an initializer that takes a function, f, which can throw. If f does not throw, then a member variable (self.result) should be set to an instance of an enum that wraps the value that f returns. If f does throw, then self.result should be set to an instance of the enum that indicates the value is absent. At the end of the initializer, self.result should not be nil. I have checked the case where the f does not throw, and the behavior is correct. However, in the case that f does throw, self.result is nil at the end of the initializer (the assert is triggered). If I single-step in the debugger, I see that self.result seems to instantaneously be set and then flashes back to being nil.
(Note: You might suggest I represent the absence of a result as nil, rather than wrapping in the enum. However, I need to model the scenario in which the result of f has not been computed yet, has been computed successfully, or an attemopt has been made to compute the result but it has failed. Hence the enum.)
Have I misunderstood how Swift 2's error handling works? Or, is the compiler/debugger etc. behaving incorrectly?
Thanks in advance.
internal enum Result<T> {
case Value(T)
case None
}
public final class MyClass<T> {
internal var result: Result<T>? = nil
private init(f: () throws -> T) {
let queueName = “some.string”
let queue = dispatch_queue_create(queueName, DISPATCH_QUEUE_CONCURRENT)
dispatch_async(queue) {
do {
let value = try f()
self.result = .Value(value)
}
catch {
self.result = .None
}
assert(self.result != nil, "Result must have value before block returns.")
}
}
}
In
self.result = .None
the left-hand side is an optional Result, therefore .None on
the right-hand side is inferred as Optional.None, and the statement
is equivalent to
self.result = nil
What you probably meant is
self.result = Result.None
and then the assertion does not fail anymore. Alternatively,
use a different enumeration value, e.g. case NoValue in your custom
type.

Swift function with Shorthand Argument Names

Is it possible to use Shorthand Argument Names with a Swift function. Closures have this feature, but since a function is in itself a closure, there might be a way to access parameters with name omitted. In detail here is what my query is:
You can implement a closure with shorthand argument name like this:
someFunction(param1, { $0 > $1 })
There is no need to provide parameter names in a closure, simply use $0, $1 etc.
For a function you may define it like so:
func functionC(Int, String) {
}
Omitting the param names here does not give any compiler error. Probably this is a swift feature. So does this mean I can access the params without name. If yes, then how?
This may be a bug or half implemented feature now because I can't find anything in the documentation about it. Using a function like you described compiles and runs fine:
func functionC(Int, String) {
println("function called")
}
functionC(10, "hello")
but attempting to use the arguments with the closure syntax $0 and $1 results in the error: Anonymous closure argument not contained in a closure which pretty clearly states you aren't allowed to use anonymous arguments in a function.
I think the purpose of this then is to be able to have the same method signature of a required function even if you don't have to use all of the arguments like this example:
protocol myProtocol{
func requiredFunc(Int, String) -> Bool
}
class myClass: myProtocol{
func requiredFunc(x: Int, String) -> Bool{
return x > 10
}
}
You can use the shorthand arguments in a closure because the compiler can infer the parameters and their types. But it is not fair to say that func functionC(Int, String) is the same as a closure with no parameter list. A closure declared the same way will not work either. Just like your function declaration, this closure is not valid because the parameters were declared:
{ (Int, String) -> Bool in
return $0 > $1
}
Short hand arguments don't work for functions. According to the compiler they work only for closures.
Coming to your stated case:
func functionC(Int, String) {
}
here it doesn't report any error because you just defined the function to take arguments of Int and String but cannot be used anywhere since they're not assigned. So there is no purpose to take this case other to verify how the compiler works.

Resources