漏洞 > 迅捷 > Enum > 字符串协议
我试图创建一个枚举,其中所有元素都是文件名,我偶然发现了一些有趣的东西。就像这样。
enum FileNames: String {
case main = #file
}
这导致了一个内部错误: (Segmentation Fault: 11)
我是能够想办法得到一个实际的错误信息的。
enum Foo: String {
case one = "\(1)"
}
Error: Raw value for enum case must be a literal
相关问题: - 是否 #file
被认为是一个字符串字面意思?- 为什么 #file
破坏枚举?是否应该在bug.swift.org上报告?- 我注意到,将 String
到 Int
和 #file
到 #line
导致同样的问题。这是一个提示吗?
我以为是这样,但我犯了一个错误。它也会导致同样的内部错误。
import UIKit
enum ColorEnum: UIColor {
case foo = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0)
}
根据苹果公司的。#file
被认为是一个字面意义。
这些也会使编译器崩溃。
enum Foo: String? {
case breaks = nil
}
23 大规模破坏的字符enum I:Int?{case a=nil}
现在崩溃的问题已经修复,已经正式合并到Swift中。Merged on GitHub这是错误报告。SR-12998
增加支持 这里支持使用魔法字元作为枚举情况的原始值。SR-13022
是的。#file
和 #line
是 文字表述 但你的程序还是不规范。
Swift语言参考 说:
字符表达式由普通字符(如字符串或数字)、数组或字典字符、游戏场字符或下列特殊字符之一组成。
#file
- String - 它出现的文件名。
#line
- Int - 它所出现的行号。[...]
让我们也注意一下语法。
literal-expression → literal
literal-expression → array-literal | dictionary-literal | playground-literal
literal-expression → #file | #line | #column | #function | #dsohandle
现在让我们考虑一下 枚举语法 你在定义。我这里只包括最相关的部分,你可以自己验证完整的推导。
enum-declaration → attributes opt access-level-modifier opt raw-value-style-enum
[...]
raw-value-style-enum → enum enum-name generic-parameter-clause opt type-inheritance-clause generic-where-clause opt { raw-value-style-enum-members }
[...]
raw-value-assignment → = raw-value-literal
raw-value-literal → numeric-literal | static-string-literal | boolean-literal
值得注意的是,只有 数形, 静态字符串, 布尔运算 是允许的。如果我们看一下他们的定义,很明显,这些。#
因此,字面意思不符合 raw-value-literal
规则。
numeric-literal → -opt integer-literal | -opt floating-point-literal
boolean-literal → true | false
static-string-literal → string-literal-opening-delimiter quoted-text opt string-literal-closing-delimiter
static-string-literal → multiline-string-literal-opening-delimiter multiline-quoted-text opt multiline-string-literal-closing-delimiter
所有相关的规则,以完全定义 静态字符串 是长,但它仍然是小事一桩。静态字符串 推不出 #file
而不能包括插值。这就是它的静态化的原因)。
所以Swift编译器拒绝你的程序确实是正确的。不过,一个现代编译器不应该简单地在一个非法程序上崩溃,所以可能值得报告这个问题。
这绝对是一个bug,所以值得向苹果提交反馈(虽然他们记录了那些#file、#function等是 特殊文字)
总之,以下的变通方法可能会对某些使用情况有所帮助。
enum FileNames {
static let main = FileNames.file(#file)
case file(String)
}