Bir kapağı Swift'te değişken olarak saklama


141

Objective-C'de, bir bloğun giriş ve çıkışını tanımlayabilir, bir yönteme aktarılan bu bloklardan birini depolayabilir ve daha sonra bu bloğu daha sonra kullanabilirsiniz:

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

Bu yüzden Swift'te denklemi yapmaya çalışıyorum:

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

Derleyici bu tamamlama bildirimini beğenmez. Suçlu olduğum için değil, ama daha sonra Swift'te ayarlanabilen ve kullanılabilecek bir kapağı nasıl tanımlayabilirim?


1
Derlediğinizde hangi hatayı alıyorsunuz?
TheLazyChap

Yanıtlar:


335

Derleyici şikayet ediyor

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

çünkü sağ taraf uygun imzanın kapatılması değildir, yani kayan bir argüman alan bir kapanış değildir. Aşağıdakiler, tamamlama işleyicisine "hiçbir şey yapma" kapatma atayacaktır:

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

ve bu kısaltılabilir

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

otomatik tür çıkarımı nedeniyle.

Ancak muhtemelen istediğiniz şey, tamamlama işleyicisinin nil bir Objective-C örnek değişkeninin başlatıldığı şekilde başlatılmasıdır nil. Swift'te bu isteğe bağlı olarak gerçekleştirilebilir :

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

Şimdi özellik otomatik olarak nil("değer yok") olarak başlatılır . Swift'te, tamamlama işleyicisinin bir değeri olup olmadığını denetlemek için isteğe bağlı bağlamayı kullanırsınız

if let handler = completionHandler {
    handler(result)
}

veya isteğe bağlı zincirleme:

completionHandler?(result)

1
"Swift'te bu, örtük olarak açılmamış bir isteğe bağlı" veya "açıkça açılmamış" (yani normal) isteğe bağlı olarak gerçekleştirilebilir
21

1
Kullanmaktan ((Float)->Void)!farklı ((Float)->Void)?mı? Başlatılmamış bir isteğe bağlı ?olarak nilzaten varsayılan olarak bildirilmiyor mu?
16'da 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 = ^() {
    ...
}

hızlı

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
Ancak bellek yönetimi otomatik olarak doğru mu yapılıyor? Çünkü Obj-C Bu özelliği "kopya" olarak belirlersiniz, ancak swift bu seçeneğe sahip değildir ve bunun yerine "güçlü" olarak tanımlanır ya da öyle mi?
Paulius Vindzigelskis

Kopyalamak neden gerekli?
Dmitry

9

Sonra senin ne olduğunu emin değilim bir örnek verdim.

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

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

completionHandler = printFloat

completionHandler(5)

completionHandlerBeyan edilen değişkeni kullanarak 5 basar .


7

Gelen Swift 4 ve 5 . İki parametre sözlüğü ve bool içeren bir kapatma değişkeni oluşturdum.

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

Kapatma değişkenini çağırma

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

5

Kapaklar olarak ilan edilebilir typealiasolarak aşağıda

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

İşlevinizde kodun herhangi bir yerinde kullanmak istiyorsanız; normal değişken gibi yazabilirsiniz

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

3

Bu da işe yarıyor:

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

-1

Benim için aşağıdaki çalışıyordu:

var completionHandler:((Float)->Void)!
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.