0

私はブロックから成り、バックグラウンドスレッドで実行される計算されたプロパティを宣言しようとしています。 したがって、このプロパティに対処すると、準備ができていないときに計算結果が返されるため、nilです。これをより良く修正するには?ありがとうございました!計算がバックグラウンドスレッドを使用するとき、計算されたプロパティを正しく宣言するにはどうすればよいですか?

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

代わりにクロージャを使用できませんでしたか?したがって、フェッチ・ユーザーが戻ると、completed()クロージャーを実行し、レコードIDを戻しますか? – arvidurs

+0

プロパティから値を非同期的に返すことはできません。 –

+5

理論的には、レスポンスを待つパターンを適用することができますが、非同期検索メカニズムの考え方は、応答を待っているメインスレッドをブロックしないようにすることです。だから、短い答えは、あなたは本当に非同期メソッドをラップするために計算されたプロパティを使うべきではないということです。ちょうど 'fetchUserRecordID'をつけてください。完了ハンドラのクロージャで 'Result '型を返す何らかのメソッドでラップしたいのであれば、それは問題ありませんが、計算されたプロパティで処理しようとしません。 – Rob

答えて

1

GCDセマフォを使用するなど、簡単な解決策があります。しかし、最初の場所では、アプローチ全体が正しくないように見えることがあります。これは、状況によっては(メインスレッドでこのプロパティを呼び出すなど)、不要なハングやデッドロックが発生する可能性があるためです。より良いアプローチは、適切な完了ハンドラを持つメソッドにそのコードを移動することです。

計算されたプロパティはメソッドを置き換えるものではありません。スコープ内に複雑な(特に非同期の)計算がある場合は、そのコードをプロパティからメソッドに移動するようにかなり設定されています。

しかし、いずれにせよ:ここ

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 
} 

あなたは非同期操作が終了するのを待ってGCDセマフォを持っています。

関連する問題