En Objective-C, vous pouvez définir l'entrée et la sortie d'un bloc, stocker l'un de ces blocs transmis à une méthode, puis utiliser ce bloc ultérieurement:
// 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);
});
...
}
Alors j'essaie de faire l'équivalent dans 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()
}
Le compilateur n'aime pas cette déclaration de completionHandler. Non pas que je le blâme, mais comment définir une fermeture pouvant être définie et utilisée ultérieurement dans Swift?
Le compilateur se plaint
var completionHandler: (Float)->Void = {}
parce que le membre de droite n'est pas une fermeture de la signature appropriée, c’est-à-dire une fermeture prenant un argument float. Les éléments suivants attribueraient une fermeture "ne rien faire" au gestionnaire d'achèvement:
var completionHandler: (Float)->Void = {
(arg: Float) -> Void in
}
et cela peut être réduit à
var completionHandler: (Float)->Void = { arg in }
en raison de l'inférence de type automatique.
Mais ce que vous voulez probablement, c'est que le gestionnaire d'achèvement soit initialisé à nil
de la même manière qu'une variable d'instance Objective-C est initialisée à nil
. Dans Swift ceci peut être réalisé avec un optionnel :
var completionHandler: ((Float)->Void)?
Maintenant, la propriété est automatiquement initialisée à nil
("pas de valeur"). Dans Swift, vous utiliseriez une liaison facultative pour vérifier si le gestionnaire d'achèvement a une valeur
if let handler = completionHandler {
handler(result)
}
ou chaînage optionnel:
completionHandler?(result)
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 = ^() {
...
}
rapide
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
...
}
J'ai fourni un exemple pas sûr si c'est ce que vous cherchez.
var completionHandler: (value: Float) -> ();
func printFloat(value: Float) {
println(value)
}
completionHandler = printFloat
completionHandler(value: 5)
Il imprime simplement 5 en utilisant la variable completionHandler
déclarée.
Dans Swift 4 et 5. J'ai créé une variable de fermeture contenant deux dictionnaire de paramètres et bool.
var completionHandler:([String:Any], Bool)->Void = { dict, success in
if success {
print(dict)
}
}
Appel de la variable de fermeture
self.completionHandler(["name":"Gurjinder singh"],true)
Les fermetures peuvent être déclarées comme typealias
comme ci-dessous
typealias Completion = (Bool, Any, Error) -> Void
Si vous souhaitez utiliser dans votre fonction n'importe où dans le code; vous pouvez écrire comme variable normale
func xyz(with param1: String, completion: Completion) {
}
Cela fonctionne aussi:
var exeBlk = {
() -> Void in
}
exeBlk = {
//do something
}
//instead of nil:
exeBlk = {}