How to properly declare a computed property, when calculation uses background threads?

三世轮回 提交于 2019-12-01 12:02:43

问题


I'm trying to declare a computed property that consists of a block, executed in the background thread. So, when I address this property, it's nil, as the computation returns the result when it is not ready. How to better correct this? Thank you!

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
}

回答1:


There's a straight-forward solution, such as using GCD semaphores. However, the entire approach doesn't seem correct in the first place, for this might cause unwanted hangs or even deadlocks in some circumstances (like calling this property in main thread). The better approach would be moving that code to a method with appropriate completion handler.

Just keep in mind that computed properties are not intended to replace methods. If there are some complex (especially asynchronous) calculations in the scope, you're pretty much set to move that code from a property to a method.

But anyway:

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
}

Here you have a GCD semaphore which awaits for async operation to finish.



来源:https://stackoverflow.com/questions/46595407/how-to-properly-declare-a-computed-property-when-calculation-uses-background-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!