Swift3 枚举中的自定义字符串

Swift3 枚举中的自定义字符串,swift3,enums,customstringconvertible,Swift3,Enums,Customstringconvertible,我在一个类中有以下枚举 enum Attributes: String, CustomStringConvertible { case eventDate case eventName case eventType case country var description: String { return self.rawValue } } 当我尝试使用以下代码时,编译器抱怨出现以下错误 var attributesList:

我在一个类中有以下枚举

enum Attributes: String, CustomStringConvertible {
    case eventDate
    case eventName
    case eventType
    case country

    var description: String {
        return self.rawValue
    }
}
当我尝试使用以下代码时,编译器抱怨出现以下错误

var attributesList: [String] {
    return [
        Attributes.eventDate, //<-- Compiler error on this row
        Attributes.eventName,
        Attributes.eventType,
        Attributes.country]
}
var attributesList:[字符串]{
返回[

Attributes.eventDate,//TL;DR-它不起作用,因为不能将
属性
s数组分配给
字符串
s数组,它们都是不匹配的类型,Swift不会在类型之间进行自动转换,需要指定显式转换


在Swift中,当您使用数组文字初始化数组时,会发生以下情况:

let words = ["hello", "world"]
  • 编译器识别出一个数组文本被分配给一个名为
    words
    的变量。由于我们没有指定
    words
    的类型,因此隐式地假设了一个数组。数组底层元素的类型是根据数组文本的内容确定的
  • 在本例中,数组文字是
    String
    类型的集合;编译器很容易理解这一点
  • 由于LHS类型是一个数组,RHS结构是一个数组文本,并且由于LHS类型(
    array
    )符合一个名为
    ExpressibleByArrayLiteral
    的预定义协议,该协议有一个关联的类型约束来匹配
    元素
    ,编译器实际上将我们的行转换为以下内容
例如:

let words = [String].init(arrayLiteral: ["hello", "world"]) // we do not call this init directly
这就是使用数组文字初始化的工作方式。在上面的示例中,由于我们没有指定数组的类型,隐式类型设置将起作用。如果我们指定了不匹配的类型,则赋值将失败,因为
ExpressibleByArrayLiteral
需要数组文字的关联
元素
类型和实际值指定要匹配的数组

因此,以下方法失败了:

let words:[String] = [1, 2] // array literal has Element=Int, array has Element=String
这还表明,
Int
String
之间没有隐式类型转换,即使
Int
符合
CustomStringConvertible

在本例中,您试图将包含
属性的数组文本分配给
字符串的数组。这是类型不匹配。这是失败的原因

如果您声明协议一致性,则以下行将起作用:

var attributesList: [CustomStringConvertible] {
    return [
        Attributes.eventDate,
        Attributes.eventName,
        Attributes.eventType,
        Attributes.country
    ]
}
// note that we have an array of CustomStringConvertible protocol,
// each element here is still of Attributes type
// a type conforming to a protocol can be cast to an instance
// of that protocol automatically
// The above initialisation works simply because the following
// also works without any further action required
// let a:CustomStringConvertible = Attributes.country
如果确实需要字符串值列表,则需要将其显式映射到字符串:

var attributesList1: [String] {
    return [
        Attributes.eventDate,
        Attributes.eventName,
        Attributes.eventType,
        Attributes.country
        ].map { $0.description }
}

var attributesList2: [String] {
    return [
        Attributes.eventDate.description,
        Attributes.eventName.description,
        Attributes.eventType.description,
        Attributes.country.description
        ]
}

TL;DR-它不起作用,因为不能将
属性
的数组分配给
字符串
的数组,它们都是不匹配的类型,Swift不会在类型之间进行自动转换,需要指定显式转换


在Swift中,当您使用数组文字初始化数组时,会发生以下情况:

let words = ["hello", "world"]
  • 编译器识别出一个数组文本被分配给一个名为
    words
    的变量。由于我们没有指定
    words
    的类型,因此隐式地假设了一个数组。数组底层元素的类型是根据数组文本的内容确定的
  • 在本例中,数组文字是
    String
    类型的集合;编译器很容易理解这一点
  • 由于LHS类型是一个数组,RHS结构是一个数组文本,并且由于LHS类型(
    array
    )符合一个名为
    ExpressibleByArrayLiteral
    的预定义协议,该协议有一个关联的类型约束来匹配
    元素
    ,编译器实际上将我们的行转换为以下内容
例如:

let words = [String].init(arrayLiteral: ["hello", "world"]) // we do not call this init directly
这就是使用数组文字初始化的工作方式。在上面的示例中,由于我们没有指定数组的类型,隐式类型设置将起作用。如果我们指定了不匹配的类型,则赋值将失败,因为
ExpressibleByArrayLiteral
需要数组文字的关联
元素
类型和实际值指定要匹配的数组

因此,以下方法失败了:

let words:[String] = [1, 2] // array literal has Element=Int, array has Element=String
这还表明,
Int
String
之间没有隐式类型转换,即使
Int
符合
CustomStringConvertible

在本例中,您试图将包含
属性的数组文本分配给
字符串的数组。这是类型不匹配。这是失败的原因

如果您声明协议一致性,则以下行将起作用:

var attributesList: [CustomStringConvertible] {
    return [
        Attributes.eventDate,
        Attributes.eventName,
        Attributes.eventType,
        Attributes.country
    ]
}
// note that we have an array of CustomStringConvertible protocol,
// each element here is still of Attributes type
// a type conforming to a protocol can be cast to an instance
// of that protocol automatically
// The above initialisation works simply because the following
// also works without any further action required
// let a:CustomStringConvertible = Attributes.country
如果确实需要字符串值列表,则需要将其显式映射到字符串:

var attributesList1: [String] {
    return [
        Attributes.eventDate,
        Attributes.eventName,
        Attributes.eventType,
        Attributes.country
        ].map { $0.description }
}

var attributesList2: [String] {
    return [
        Attributes.eventDate.description,
        Attributes.eventName.description,
        Attributes.eventType.description,
        Attributes.country.description
        ]
}

如果有人想否决某个问题,那么该人应该有礼貌地解释原因。如果有人想否决某个问题,那么该人应该有礼貌地解释原因。或者在最后一个示例中,您可以使用
rawValue
而不是
description
。或者您可以使用
rawValue
而不是
descr最后一个示例中的iption