在 Swift 中将闭包存储为变量

在 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);
});
...
}

所以我试着用斯威夫特的同义词:

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()
}

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

124278 次浏览

我举了个例子,不知道这是不是你想要的。

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


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


completionHandler = printFloat


completionHandler(5)

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

编译器抱怨

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

因为右边不是适当签名的闭包,即闭包取 一个浮点参数。下面将为 完成处理程序:

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

这可以简化为

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

由于自动类型推断。

但是 您可能需要的是将完成处理程序初始化为 nil 就像 Objective-C 实例变量被初始化为 nil一样 这可以通过 可以选择来实现:

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

现在该属性被自动初始化为 nil(“ no value”)。 在 Swift 中,可以使用可选绑定来检查 完成处理程序有一个值

if let handler = completionHandler {
handler(result)
}

或者可选择的链条:

completionHandler?(result)

对我来说,以下方法是有效的:

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

目标 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 = ^() {
...
}

斯威夫特

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

这也行得通:

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

闭包可以像下面这样声明为 typealias

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

如果希望在函数中使用代码中的任何位置,可以像普通变量那样编写

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

斯威夫特4号和5号中,我创建了一个包含两个参数 dictionary 和 bool 的闭包变量。

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

调用闭包变量

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

根据你的需要,有一个附加的可接受的答案。你也可以这样实现它:

var parseCompletion: (() ->Void)!

然后在一些函数中赋值给它

func someHavyFunc(completion: @escaping () -> Void){
self.parseCompletion = completion
}

在第二个函数中使用它

func someSecondFunc(){
if let completion = self.parseCompletion {
completion()
}
}

请注意,这里必须使用 @escaping参数