iOS RxSwift - Как развернуть `Optional<Optional <T >>` или `T??`?
Я использую логику ниже, чтобы проверить состояние моего предмета с помощью RxBlocking. Я получаю странное значение Int??
снаружи try? subject.verifier.toBlocking().first()
,
Синтаксис ниже радует компилятор, но у меня кровоточат глаза.
Как получить развернутое значение от ожидания RXBlocking?
func checkSubjectState() -> Int
{
let updatedChecksum = try? subject.verifier.toBlocking().first() ?? 0
return updatedChecksum ?? 0
}
let expectedCheckSum = checkSubjectState()
expect(expectedCheckSum).to(equal(knownValue))
4 ответа
Вот ответ, который не требует от вас определения каких-либо собственных функций:
return (try? subject.verifier.toBlocking().first()).flatMap { $0 } ?? 0
Да так first()
может бросить, и он возвращает необязательный тип, так try? first()
возвращает Optional<Optional<Int>>
или же Int??
, Честно говоря, я думаю, что first()
функция плохо написана. Следует либо бросить, либо вернуть необязательно, а не оба.
Вы могли бы написать flattened
оператор:
public protocol OptionalType {
associatedtype Wrapped
var value: Wrapped? { get }
}
extension Optional: OptionalType {
public var value: Wrapped? {
return self
}
}
extension Optional where Wrapped: OptionalType {
var flattened: Wrapped.Wrapped? {
switch self {
case let .some(opt):
return opt.value
case .none:
return nil
}
}
}
Что позволит вам сделать:
let expectedCheckSum = (try? subject.verifier.toBlocking().first()).flattened ?? 0
Думаете ли вы, что оно того стоит или нет - ваш звонок.
Есть две другие альтернативы, позволяющие избежать двойной необязательности путем обработки ошибки.
Первые вручают ошибку звонящему
func checkSubjectState() throws -> Int
{
return try subject.verifier.toBlocking().first() ?? 0
}
Второй добавляет do - catch
блок
func checkSubjectState() -> Int
{
do { return try subject.verifier.toBlocking().first() ?? 0 }
catch { return 0 }
}
Я нашел другое решение, которое, я думаю, вам может понравиться больше:
infix operator ???: NilCoalescingPrecedence
func ???<T>(opt: T??, val: @autoclosure () -> T) -> T {
return ((opt ?? val()) ?? val())
}
Вышесказанное позволит вам просто:
return (try? subject.verifier.toBlocking().first()) ??? 0
Я пытался дать оператору более высокий приоритет, чем try?
так что парены не понадобятся, но я не мог найти способ сделать это.