I have been trying to figure out this small thing which was quite easy with Objective C, but could not solve with Swift.
var loginViewController: SSLoginViewController
let completion = {
loginViewController.presentViewController(SSFeedViewController(), animated: true, completion: nil)
}
loginViewController = SSLoginViewController(completion: completion)
The intention here is to pass SSLoginViewController a completionBlock to present another view controller. But, the code above gives error.
Variable 'loginViewController' captured by closure before being initialized.
Delcaring the uninitialized variable as __block, the Objective C block would take the changed value from within a block.
It would be something like this in Objective C,
__block SSLoginViewController *loginViewController;
dispatch_block_t completion = ^ {
[loginViewController presentViewController:[[SSFeedViewController alloc] init] animated: YES completion:nil]
};
loginViewController = [[SSLoginViewController alloc] initWithCompletion:completion];
How can the similar behavior be achieved with Swift ?
It should be initialized to
nil
(that's what's happening in your Objective-C code anyway; in Objective-C ARC, managed object pointers are initialized tonil
if not otherwise initialized). This means it will need to be optional. You can use implicitly-unwrapped optional to not have to deal with optional syntax since you know it's only going to benil
temporarily.An additional problem, which also exists in your Objective-C code, is that there will likely be a retain cycle. The
SSLoginViewController
object probably stores and thus has a strong reference to the completion block, and the block has a strong reference to theSSLoginViewController
object. If you know that the completion block will only exists while theSSLoginViewController
object is alive, then you can have it capture a weak reference tologinViewController
: