0

In my project, trying to use capture lists with closures, but I have injected dependencies that are implicitly unwrapped since I guarantee that they will be populated by dependency injection. I discovered that using a capture list resulted in a compile error.

var forced: String!

func example() {
    escapingClosure { [forced] in
        let new = forced + "something" //has to be unwrapped again despite being forced
        print(new)
    }
}


func escapingClosure(closurce: @escaping () -> ()) {
    //do something
}

Here is the error:

enter image description here

I can resolve this by force unwrapping inside the closure, but I'm surprised that is necessary given the implicitly unwrapped declaration. Why is that step necessary? Is this a bug or a feature?

Chuck Krutsinger
  • 2,830
  • 4
  • 28
  • 50
  • Please read https://swift.org/blog/iuo/ – matt Oct 18 '18 at 13:00
  • this is meaningless how you set forced in [forced] and your closure doesn't return anything – Shehata Gamal Oct 18 '18 at 13:00
  • 2
    A couple of related Q&As: https://stackoverflow.com/q/39537177/2976878 & https://stackoverflow.com/q/39633481/2976878. If you want `forced` to be a copy of the unwrapped value in the closure, one option would be to force unwrap it in the capture list, e.g `[forced = forced!] in`. – Hamish Oct 18 '18 at 13:23
  • @Hamish is spot on. Those two related Q&As are exactly on topic and I did not find them. This question should probably be deleted as a duplication. – Chuck Krutsinger Oct 18 '18 at 13:56

1 Answers1

2

You can declare implicit unwrappedness, but you cannot propagate it. There is actually no such thing as an implicitly unwrapped Optional type, so when you pass or assign or capture a value declared as that type, it reverts to a normal Optional. For example:

 var forced: String! = "test"
 let x = forced

You will find that x is an ordinary Optional, a String?. Your captured value is like that.

matt
  • 515,959
  • 87
  • 875
  • 1,141