クロージャーを変数としてSwiftに保管する


140

Objective-Cでは、ブロックの入力と出力を定義し、メソッドに渡されたブロックの1つを保存して、後でそのブロックを使用できます。

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

コンパイラは、complementationHandlerの宣言を好みません。非難するわけではありませんが、後でSwiftで設定して使用できるクロージャーをどのように定義しますか?


1
コンパイルするとどのようなエラーが発生しますか?
TheLazyChap 14

回答:


334

コンパイラは文句を言う

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

右側が適切なシグネチャのクロージャではないためです。つまり、float引数を取るクロージャです。次の例では、完了ハンドラに「何もしない」クロージャを割り当てます。

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

これは以下のように短縮できます

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

自動型推論による。

しかし、おそらくあなたが望むのはnil 、Objective-Cインスタンス変数がに初期化されるのと同じ方法で、完了ハンドラが初期化されるということnilです。Swiftではこれはオプションで実現できます

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

これで、プロパティは自動的にnil(「値なし」)に初期化されます。Swiftでは、オプションのバインディングを使用して、完了ハンドラが値を持っていることを確認します

if let handler = completionHandler {
    handler(result)
}

またはオプションの連鎖:

completionHandler?(result)

1
「Swiftでは、これは暗黙的にアンラップされたオプションで実現できます」または「明示的にアンラップされた」(つまり、通常の)オプション
newacct

1
とは((Float)->Void)!違うものを使用しています((Float)->Void)?か?初期化されていないオプションを?デフォルトでnilすでに宣言していませんか?
Suragch

43

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

迅速

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

1
しかし、メモリ管理は自動的に正しく処理されますか?Obj-Cではそのプロパティを「コピー」に指定していますが、swiftにはそのオプションがないようで、代わりに「強い」と定義されているのでしょうか。
Paulius Vindzigelskis 2016年

なぜそれをコピーする必要があるのですか?
ドミトリー

9

これがあなたが求めているものかどうかわからない例を提供します。

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

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

completionHandler = printFloat

completionHandler(5)

completionHandler宣言された変数を使用して5を出力するだけです。


7

スイフト4と5。2つのパラメーター辞書とboolを含むクロージャー変数を作成しました。

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

クロージャー変数を呼び出す

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

5

クロージャはtypealias以下のように宣言できます

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

コード内の任意の場所で関数で使用したい場合、通常の変数のように書くことができます

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

3

これも機能します:

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

-1

私にとっては以下が働いていました:

var completionHandler:((Float)->Void)!
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.