Swift 4.2, Xcode 10.1
В приложении обработки заказов, над которым я работаю, пользователь может выполнять поиск заказов, уже обработанных или отправленных. Когда это произойдет, он проверит, есть ли у него кэш заказов, а если нет, то заполняет этот кэш с помощью асинхронного запроса API, а затем снова проверяет кэш.
Функция, которая заполняет кэш, является частной статической функцией, которая принимает экранирующий обработчик завершения. Когда бы я ни использовал этот обработчик завершения в прошлом, все, что мне нужно было сделать, это добавить замыкание в конце вызова функции. Это было до того, как мне было поручено создать кеш всех данных, где это возможно, и использовать API только для пополнения этого кеша. С тех пор эта функция стала закрытой, потому что больше никогда не будет необходимости вызывать API из любой точки, кроме этого класса.
Теперь, когда я помещаю замыкание непосредственно после вызова функции, оно выдает мне ошибку, которая в основном говорит, что я передаю замыкание @nonescaping вместо замыкания @escaping:
"Cannot invoke 'getAndCacheAPIData' with an argument list of type '(type: Codable.Type, (String?) -> Void)', Expected an argument list of type '(type: CodableClass.Type, @escaping (String?) -> Void)'"
Раньше мне никогда не приходилось явно объявлять, что замыкание будет @escaping, никоим образом это не представляется возможным. Я подозреваю, что, поскольку функция является как частной, так и статической, возникает некоторая проблема, возникающая из-за того, что замыкания являются @escaping. Я вне моей глубины. Я мог бы попытаться преобразовать статический класс в одноэлементный, но я не решаюсь рефакторизовать кучу рабочего кода из-за одной ошибки, пока я не буду абсолютно уверен, что изменение решит проблему, и что то, что я пытаюсь сделать, не невозможно, если я не изменю свой подход.
Вот код:
public static func fillSearchResultArray<ManagedClass: NSManagedObject>(query:String, parameters:[String], with type: ManagedClass.Type, completionHandler: @escaping (String?)->Void)
{
let codableType:Codable.Type
switch type
{
case is ClientTable.Type:
codableType = ClientData.self
case is OrderTable.Type:
codableType = OrderData.self
case is ProductTable.Type:
codableType = ProductData.self
default:
completionHandler("Unrecognized type.")
return
}
let fetchedData:[ManagedClass]
do
{
fetchedData = try PersistenceManager.shared.fetch(ManagedClass.self)
}
catch
{
completionHandler(error.localizedDescription)
return
}
if fetchedData.isEmpty
{
AppNetwork.getAndCacheAPIData(type: codableType)//error here
{(firstErrorString) in
//move search array data to the cache
if firstErrorString.exists
{
completionHandler(error)
}
else
{
AppNetwork.fillSearchResultArray(query: query, parameters: parameters, type: type)
{ errorString in
completionHandler(errorString)
}
}
}
return
}
else
{ ...
Подпись вызываемой функции:
private static func getAndCacheAPIData <CodableClass: Any & Codable>(type:CodableClass.Type, completionHandler: @escaping (String?)->Void)
Почему swift выводит, что это закрытие является @nonescaping по умолчанию, когда до него всегда делалось @escaping?