Здесь у вас есть семафор GCD, который ожидает завершения асинхронной операции.

аюсь объявить вычисляемое свойство, которое состоит из блока, выполняемого в фоновом потоке. Поэтому, когда я обращаюсь к этому свойству, оно равно 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
}
 arvidurs06 окт. 2017 г., 00:09
Не могли бы вы использовать вместо этого закрытие? Поэтому, когда пользователь извлечения возвращается, он выполняет завершение завершения () и возвращает идентификатор записи?
 Rob06 окт. 2017 г., 00:13
Теоретически вы могли бы применить шаблоны, чтобы заставить это ждать ответа, но вся идея асинхронных механизмов поиска состоит в том, чтобы гарантировать, что вы не заблокируете основной поток, ожидающий некоторого ответа. Итак, краткий ответ заключается в том, что вам не следует использовать вычисляемое свойство для переноса асинхронного метода. Просто придерживайтесьfetchUserRecordID, Если вы хотите обернуть его в какой-то метод, который возвращает вашResult<T> введите закрытие обработчика завершения, это нормально, но не пытайтесь делать это с вычисляемым свойством.
 Josh Caswell06 окт. 2017 г., 00:12
Вы не можете асинхронно возвращать значение из свойства.
 Hexfire06 окт. 2017 г., 06:42
Роб прав. Это не подходящее место для кода, подобного этому, для помещения в свойство. Для параллелизма и многопоточности не забудьте также изучитьНОД (Grand Central Dispatch) темы, чтобы узнать, как правильно управлять фоновыми задачами.

Ответы на вопрос(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, который ожидает завершения асинхронной операции.

Ваш ответ на вопрос