Jay Dub Jay Dub - 1 year ago 149
Swift Question

store a closure as a variable in Swift

In Objective-C, you can define a block's input and output, store one of those blocks that's passed in to a method, then use that 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];
_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 do the equivilant in Swift:

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

locationManager = CLLocationManager()
region = CLBeaconRegion()
timer = NSTimer()


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

The compiler doesn't like that declaration of completionHandler. Not that I blame it, but, how do I define a closure that can be set and used later in Swift?

Answer Source

The compiler complains on

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

because the right-hand side is not a closure of the appropriate signature, i.e. a closure taking a float argument. The following would assign a "do nothing" closure to the completion handler:

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

and this can be shortened to

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

due to the automatic type inference.

But what you probably want is that the completion handler is initialized to nil in the same way that an Objective-C instance variable is inititialized to nil. In Swift this can be realized with an optional:

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

Now the property is automatically initialized to nil ("no value"). In Swift you would use optional binding to check of a the completion handler has a value

if let handler = completionHandler {

or optional chaining:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download