Возвращаемое значение вычисляемого свойства Swift

У меня есть вычисляемое свойство, которое, как ожидается, вернет объект или ноль в случае сбоя.

var findRequest: Book {
    get {
        var foundRequest: Book!
        API.requestBook(book: bookRequest) { book in
            if book != nil {
                foundRequest = book!
            } else {
                print("Could not find book")
                foundRequest = nil
            }
        }
        return foundRequest
    }
}

Когда я запускаю код, я получаю неожиданно найденный nil при развертывании ошибки необязательного значения в строке возврата foundRequest. Похоже, код пропускает мою функцию закрытия и сразу переходит к возврату.

Спасибо


person user7684436    schedule 25.08.2017    source источник
comment
Возможно, запрос асинхронный?   -  person Martin R    schedule 25.08.2017


Ответы (2)


Есть несколько проблем с вашей реализацией. Прежде всего, вы не должны определять foundRequest как неявно развернутый необязательный параметр, если есть вероятность, что его значение будет nil. Во-вторых, вы возвращаете значение вне обработчика завершения асинхронной функции API.requestBook, поэтому вы возвращаете значение до того, как foundRequest сможет получить значение, и, следовательно, вы возвращаете значение по умолчанию nil, которое будет принудительно развернуто из-за неявно развернутого необязательное объявление, отсюда и ошибка.

Более того, вы не должны делать асинхронный запрос внутри геттера вычисляемого свойства, поскольку предполагается, что вычисляемые свойства сразу же возвращают значение.

Вы должны полностью изменить свою реализацию, чтобы сделать findRequest функцией, возвращающей значение типа Book внутри обработчика завершения.

func findRequest(bookRequest: URLRequest, completion: @escaping (Book?->Void)){
        API.requestBook(book: bookRequest) { book in
            if let book = book {
                completion(book)
            } else {
                print("Could not find book")
                completion(nil)
            }
        }
}

Вы можете вызвать функцию следующим образом:

findRequest(bookRequest: yourRequest, completion: { book in
    if let book = book {
        //use the returned value
    } else {
        print("Book not found")
    }
})

Возможно, вам придется изменить тип bookRequest с URLRequest в зависимости от того, каким должен быть тип входного параметра book.

person Dávid Pásztor    schedule 25.08.2017
comment
Спасибо - не знал, что CP не будет ждать, пока не завершится закрытие. будет рефакторинг. - person user7684436; 25.08.2017

У меня есть вычисляемое свойство, которое, как ожидается, вернет объект или ноль в случае сбоя.

Тогда вам, вероятно, следует определить это как:

var findRequest: Book? {
    // ...

(обратите внимание на "?" после Book)

Кроме того, как упоминал Мартин в комментариях, получатель вашего вычисляемого свойства должен сразу же возвращать значение, но вы делаете то, что выглядит как асинхронный вызов для извлечения значения. Сам геттер возвращается сразу же, до вызова обработчика завершения. Сторона, обращающаяся к свойству, не может получить фактическое значение, возвращаемое API.

person Nicolas Miari    schedule 25.08.2017
comment
Спасибо. Так будет ли на данный момент вызов функции лучше, или я все еще могу использовать CP? - person user7684436; 25.08.2017
comment
Да, но функция, которая принимает обработчик завершения. Вы ничего не можете сделать, пока не будет вызвано замыкание, в этом весь смысл асинхронных вызовов. - person Nicolas Miari; 25.08.2017