Связанное значение в условной привязке должно иметь необязательный тип
У меня есть протокол, определенный:
protocol Usable {
func use()
}
и класс, который соответствует этому протоколу
class Thing: Usable {
func use () {
println ("you use the thing")
}
}
Я хотел бы программно проверить, соответствует ли класс Thing используемому протоколу.
let thing = Thing()
// Check whether or not a class is useable
if let usableThing = thing as Usable { // error here
usableThing.use()
}
else {
println("can't use that")
}
Но я получаю ошибку
Bound value in a conditional binding must be of Optional Type
Если я попробую
let thing:Thing? = Thing()
Я получаю ошибку
Cannot downcast from 'Thing?' to non-@objc protocol type 'Usable'
Я тогда добавляю @objc
к протоколу и получите ошибку
Forced downcast in conditional binding produces non-optional type 'Usable'
В какой момент я добавляю ?
после as
, который, наконец, исправляет ошибку.
Как я могу достичь этой функциональности с помощью условного связывания с протоколом не @objc, так же, как и в "Advanced Swift" 2014 WWDC Video?
5 ответов
Вы можете получить его для компиляции, сделав приведение как Usable? вместо использования, как это:
// Check whether or not a class is useable
if let usableThing = thing as Usable? { // error here
usableThing.use()
}
else {
println("can't use that")
}
Это работает для меня на детской площадке
protocol Usable {
func use()
}
class Thing: Usable {
func use () {
println ("you use the thing")
}
}
let thing = Thing()
let testThing : AnyObject = thing as AnyObject
if let otherThing = testThing as? Thing {
otherThing.use()
} else {
println("can't use that")
}
Как упоминалось в документе Swift, is
Оператор - это тот парень, который нужен вам для работы:
Оператор is во время выполнения проверяет, относится ли выражение к указанному типу. Если так, это возвращает истину; в противном случае возвращается false.
Проверка не должна быть известна как истинная или ложная во время компиляции.
Таким образом, следующий тест, как правило, будет то, что вам нужно:
if thing is Usable {
usableThing.use()
} else {
println("can't use that")
}
Однако, как указывает документ, Swift может обнаружить во время компиляции, что выражение всегда истинно, и объявляет ошибку, чтобы помочь разработчику.
Вы получаете
Bound value in a conditional binding must be of Optional Type
так как thing as Usable
должен возвращать необязательный тип, чтобы сделать его as?
должен решить проблему. К сожалению, ошибка все еще сохраняется по какой-то странной причине. Во всяком случае, я нашел способ обойти это, чтобы извлечь присвоение переменной внутри оператора if
let thing = Thing()
let usableThing = thing as? Usable
if useableThing {
usableThing!.use()
}
else {
println("can't use that")
}
Быстрые протоколы не работают в Playgrounds в первой бета-версии, вместо этого попробуйте построить реальный проект.