1. ホーム
  2. swift

[解決済み] Swiftでクロージャを変数として格納する

2022-04-28 04:38:49

質問

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

だから、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()
}

completionHandlerの宣言がコンパイラに嫌われた。私はそれを非難するわけではありませんが、どのように私はSwiftで後で設定し、使用することができるクロージャを定義するのでしょうか?

解決方法は?

でコンパイラが文句を言う。

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

というのは,右辺が適切なシグネチャを持つクロージャ,すなわち を引数にとります。以下のようにすると、"do nothing"クロージャが割り当てられます。 完了ハンドラです。

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)