【发布时间】:2020-08-05 13:05:32
【问题描述】:
考虑以下枚举
enum Text: Equatable {
case plain(String)
case attributed(NSAttributedString)
}
我已经使它符合ExpressibleByStringLiteral
extension Text: ExpressibleByStringLiteral {
public typealias StringLiteralType = String
public init(stringLiteral value: StringLiteralType) {
self = .plain(value)
}
}
有了这一切,我可以像我期望的那样做以下事情:
let text: Text = "Hello" // .plain("Hello")
let text2: Text? = "Hello" // .plain("Hello")
但我得到以下编译器错误:
let nilString: String? = nil
let text3: Text? = nilString // Cannot convert value of type 'String?' to expected argument type 'Text?'
func foo(text: Text?) { /** foo **/ }
let text = "Hello"
foo(text: text) // Cannot convert value of type 'String' to expected argument type 'Text?'
func bar(text: Text?) { /** bar **/ }
bar(text: nilString) // Cannot convert value of type 'String?' to expected argument type 'Text?'
我怎样才能让这些工作?
我也尝试过扩展 Optional: ExpressibleByStringLiteral where Wrapped: ExpressibleByStringLiteral,但这没有帮助。
【问题讨论】:
-
展示你的 foo 和 bar 实现。为什么在使用字符串字面量初始化对象时声明对象是可选的?
-
@LeoDabus 为了这个例子。在实际代码中,我使用接受
String?的函数并调用其他需要Text?的函数。foo和bar都没有实现,因为单独的代码会引发编译器错误 -
只处理你的选项。检查它的可选性并打开它有什么问题?
-
Resuming “StringLiteralType 的有效类型是 String 和 StaticString。” 如果您想在初始化 Text 时处理可选字符串,只需为此创建一个可出错的初始化程序。
init?(_ string: String?) {guard let string = string else { return nil }self = .plain(string)}然后let text3 = Text(nilString) -
nilString.map(Text.plain)