Store closure as a variable in Swift

In Objective-C, you can determine the input and output of a block, save one of those blocks that were passed to the method, and then use this block later:

// in .h typedef void (^APLCalibrationProgressHandler)(float percentComplete); typedef void (^APLCalibrationCompletionHandler)(NSInteger measuredPower, NSError *error); // in .m @property (strong) APLCalibrationProgressHandler progressHandler; @property (strong) APLCalibrationCompletionHandler completionHandler; - (id)initWithRegion:(CLBeaconRegion *)region completionHandler:(APLCalibrationCompletionHandler)handler { self = [super init]; if(self) { ... _completionHandler = [handler copy]; .. } return self; } - (void)performCalibrationWithProgressHandler:(APLCalibrationProgressHandler)handler { ... self.progressHandler = [handler copy]; ... dispatch_async(dispatch_get_main_queue(), ^{ _completionHandler(0, error); }); ... } 

So, I'm trying to make equivilant in Swift:

 var completionHandler:(Float)->Void={} init() { locationManager = CLLocationManager() region = CLBeaconRegion() timer = NSTimer() } convenience init(region: CLBeaconRegion, handler:((Float)->Void)) { self.init() locationManager.delegate = self self.region = region completionHandler = handler rangedBeacons = NSMutableArray() } 

The compiler does not like this completeHandler declaration. Not that I blame him, but how to identify a closure that you can install and use later in Swift?

+128
closures swift objective-c-blocks
Jul 07 '14 at 5:28
source share
7 answers

The compiler complains about

 var completionHandler: (Float)->Void = {} 

since the right side is not a closure of the corresponding signature, i.e. a closure that takes a float argument. The following will assign the closure to a "do nothing" completion handler:

 var completionHandler: (Float)->Void = { (arg: Float) -> Void in } 

and it can be reduced to

 var completionHandler: (Float)->Void = { arg in } 

due to automatic type inference.

But , what you probably want is that the completion handler is initialized to nil in the same way that the Objective-C instance variable is initialized to nil . In Swift, this can be implemented using the option:

 var completionHandler: ((Float)->Void)? 

Now the property is automatically initialized to nil ("no value"). In Swift, you must use an optional binding to verify the completion handler matters

 if let handler = completionHandler { handler(result) } 

or optional chain:

 completionHandler?(result) 
+305
Jul 07 '14 at 7:09
source share

Objective-c

 @interface PopupView : UIView @property (nonatomic, copy) void (^onHideComplete)(); @end @interface PopupView () ... - (IBAction)hideButtonDidTouch:(id sender) { // Do something ... // Callback if (onHideComplete) onHideComplete (); } @end PopupView * popupView = [[PopupView alloc] init] popupView.onHideComplete = ^() { ... } 

Swift

 class PopupView: UIView { var onHideComplete: (() -> Void)? @IBAction func hideButtonDidTouch(sender: AnyObject) { // Do something .... // Callback if let callback = self.onHideComplete { callback () } } } var popupView = PopupView () popupView.onHideComplete = { () -> Void in ... } 
+34
Jul 18 '15 at 2:28
source share

I will give an example, not sure if this is what you need.

 var completionHandler: (value: Float) -> (); func printFloat(value: Float) { println(value) } completionHandler = printFloat completionHandler(value: 5) 

It just prints 5 using the declared completionHandler variable.

+6
Jul 07 '14 at 7:02
source share

In Swift 4 and 5 . I created a closure variable containing two parameter dictionaries and a bool.

  var completionHandler:([String:Any], Bool)->Void = { dict, success in if success { print(dict) } } 

Call closing variable

 self.completionHandler(["name":"Gurjinder singh"],true) 
+6
Nov 17 '17 at 17:54 on
source share

Closures can be declared as typealias as below

 typealias Completion = (Bool, Any, Error) -> Void 

If you want to use in your function somewhere in the code; you can write as a regular variable

 func xyz(with param1: String, completion: Completion) { } 
+4
Apr 12 '17 at 14:13
source share

This also works:

 var exeBlk = { () -> Void in } exeBlk = { //do something } //instead of nil: exeBlk = {} 
+3
Aug 13 '15 at 7:42
source share

For me, the following worked:

 var completionHandler:((Float)->Void)! 
-one
Apr 26 '15 at 20:38
source share



All Articles