将闭包作为变量存储在Swift中

时间:2022-04-16 14:02:17

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:

在Objective-C中,你可以定义一个块的输入和输出,存储传递给一个方法的其中一个块,然后以后再使用这个块:

// 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 do the 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 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?

编译器不喜欢completionHandler的声明。不是我责怪它,而是我如何定义一个可以在Swift中设置和使用的闭包?

7 个解决方案

#1


260  

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:

但是您可能想要的是,完成处理程序被初始化为nil,就像Objective-C实例变量被初始化为nil一样。在Swift中,这可以通过以下选项实现:

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

现在属性被自动初始化为nil(“无值”)。在Swift中,您将使用可选绑定检查完成处理程序是否具有值

if let handler = completionHandler {
    handler(result)
}

or optional chaining:

或可选的链接:

completionHandler?(result)

#2


27  

Objective-C

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 
    ...
}

#3


3  

I've provide an example not sure if this is what you're after.

我提供了一个例子,不确定这是否是你想要的。

var completionHandler: (value: Float) -> ();

func printFloat(value: Float) {
    println(value)
}

completionHandler = printFloat

completionHandler(value: 5)

It simply prints 5 using the completionHandler variable declared.

它只使用声明的completionHandler变量打印5。

#4


3  

In swift 4. I created a closure variable containing two parameter dictionary and bool.

斯威夫特4。我创建了一个包含两个参数字典和bool的闭包变量。

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

Calling the closure variable

调用闭包变量

self.completionHandler(["name":"Gurjinder singh"],true)

#5


2  

Closures can be declared as typealias as below

闭包可以声明为如下所示的类型别名

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

If you want to use in your function anywhere in code; you can write like normal variable

如果你想在函数中使用任何代码;可以像普通变量一样写

func xyz(with param1: String, completion: Completion) {
}

#6


1  

This works too:

其工作原理:

var exeBlk = {
    () -> Void in
}
exeBlk = {
    //do something
}
//instead of nil:
exeBlk = {}

#7


-1  

For me following was working:

对我来说,跟随是有效的:

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

#1


260  

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:

但是您可能想要的是,完成处理程序被初始化为nil,就像Objective-C实例变量被初始化为nil一样。在Swift中,这可以通过以下选项实现:

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

现在属性被自动初始化为nil(“无值”)。在Swift中,您将使用可选绑定检查完成处理程序是否具有值

if let handler = completionHandler {
    handler(result)
}

or optional chaining:

或可选的链接:

completionHandler?(result)

#2


27  

Objective-C

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 
    ...
}

#3


3  

I've provide an example not sure if this is what you're after.

我提供了一个例子,不确定这是否是你想要的。

var completionHandler: (value: Float) -> ();

func printFloat(value: Float) {
    println(value)
}

completionHandler = printFloat

completionHandler(value: 5)

It simply prints 5 using the completionHandler variable declared.

它只使用声明的completionHandler变量打印5。

#4


3  

In swift 4. I created a closure variable containing two parameter dictionary and bool.

斯威夫特4。我创建了一个包含两个参数字典和bool的闭包变量。

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

Calling the closure variable

调用闭包变量

self.completionHandler(["name":"Gurjinder singh"],true)

#5


2  

Closures can be declared as typealias as below

闭包可以声明为如下所示的类型别名

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

If you want to use in your function anywhere in code; you can write like normal variable

如果你想在函数中使用任何代码;可以像普通变量一样写

func xyz(with param1: String, completion: Completion) {
}

#6


1  

This works too:

其工作原理:

var exeBlk = {
    () -> Void in
}
exeBlk = {
    //do something
}
//instead of nil:
exeBlk = {}

#7


-1  

For me following was working:

对我来说,跟随是有效的:

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