0

J'essaie de déclarer une propriété calculée constituée d'un bloc, exécutée dans le thread d'arrière-plan. Donc, quand j'adresse cette propriété, c'est nul, car le calcul retourne le résultat quand il n'est pas prêt. Comment mieux corriger cela? Je vous remercie!Comment déclarer correctement une propriété calculée, lorsque le calcul utilise des threads d'arrière-plan?

enum Result<T> { 
    case error(error: Error) 
    case success(data: T) 
} 

var userID: Result<CKRecordID>? { 

    var result: Result<CKRecordID>? = nil 

    container.fetchUserRecordID { recordID, error in 
    if let error = error { result = .error(error: error) } 
    if let recordID = recordID { result = .success(data: recordID) } 
    } 

    return result 
} 
+0

Ne pourriez-vous pas utiliser une fermeture à la place? Donc, quand l'utilisateur récupère, il exécute une fermeture completed() et retourne l'identifiant d'enregistrement? – arvidurs

+0

Vous ne pouvez pas renvoyer de manière asynchrone une valeur d'une propriété. –

+5

Théoriquement, vous pouvez appliquer des modèles pour faire attendre la réponse, mais l'idée générale des mécanismes de récupération asynchrone est de s'assurer que vous ne bloquez pas le thread principal qui attend une réponse. Donc, la réponse courte est que vous ne devriez vraiment pas utiliser la propriété calculée pour envelopper une méthode asynchrone. Il suffit de coller avec 'fetchUserRecordID'. Si vous voulez l'inclure dans une méthode qui renvoie votre type 'Result ' dans une fermeture de gestionnaire d'achèvement, c'est bien, mais n'essayez pas de faire avec une propriété calculée. – Rob

Répondre

1

Il existe une solution simple, telle que l'utilisation de sémaphores GCD. Cependant, l'approche entière ne semble pas correcte en premier lieu, car cela peut provoquer des blocages indésirables ou même des blocages dans certaines circonstances (comme appeler cette propriété dans le thread principal). La meilleure approche serait de déplacer ce code vers une méthode avec un gestionnaire d'achèvement approprié. Gardez à l'esprit que les propriétés calculées ne sont pas destinées à remplacer les méthodes. S'il existe des calculs complexes (en particulier asynchrones) dans la portée, vous êtes à peu près prêt à déplacer ce code d'une propriété vers une méthode.

Mais de toute façon:

var userID: Result<CKRecordID>? { 

    var result: Result<CKRecordID>? = nil 

    var sema = DispatchSemaphore(value: 0) 

    container.fetchUserRecordID { recordID, error in 
     if let error = error { result = .error(error: error) } 
     if let recordID = recordID { result = .success(data: recordID) } 

     sema.signal() 
    } 

    _ = sema.wait(timeout: .distantFuture) 

    return result 
} 

Ici vous avez un sémaphores GCD qui attend pour le fonctionnement async pour terminer.