我有一个带有值的枚举:
enum Types {
case A
case B
case C
case D
}
var tableViewDataSource: [Types] = [.A, .B, .C, .D]
我要满足以下条件:
let pickerSelectingFields: [Types] = [.A, .B, .C, .D]
let indexes = pickerSelectingFields.map { tableViewDataSource.firstIndex(of: $0) }
if indexes.contains(textField.tag) {
// Working
}
当我尝试将所有内容制作成一行时,如下所示它显示错误:
闭包中不包含匿名闭包参数
代码如下:
if ([.A, .B, .C, .D] as? [Types]).map { tableViewDataSource.firstIndex(of: $0) }
.contains(textField.tag)
我在这里做什么错了?
答案 0 :(得分:2)
if ([.A, .B, .C, .D] as? [Types]).map { tableViewDataSource.firstIndex(of: $0) }
.contains(textField.tag)
我在这里做什么错了?
有两个问题。
首先,您使用as?
而不是as
。使用条件强制转换as?
时,结果为[Types]?
:可选 [Types]
。然后,Swift使用map
的可选版本,您通常会朝错误的方向前进。
您需要使用as [Types]
,因为您只是在告诉Swift将[.A, .B, .C, .D]
解释为[Types]
。
第二个问题是,由于您是在一行中执行此操作,因此(
的结束处需要额外的括号)
,map
,因为Swift不喜欢{
之后的多个if
。在不弄清楚括号的情况下,它将把{
闭包中的第一个map
解释为if
的 then 块的开始。
所以:
if ([.A, .B, .C, .D] as [Types]).map({ tableViewDataSource.firstIndex(of: $0) }).contains(textField.tag) {
// do something
}
将起作用。
您也可以只显式地键入数组的一项,然后Swift会将整个数组解释为[Types]
,如下所示:
if [Types.A, .B, .C, .D].map({ tableViewDataSource.firstIndex(of: $0) }).contains(textField.tag) {
// do something
}
注意:
常见的Swift约定是,以{em>大写字母开头class
,struct
和enum
类型名称,并启动变量,方法和枚举小写字母的值。
因此您的enum
可以写为:
enum Types {
case a, b, c, d
}
答案 1 :(得分:1)
一种解决方案是使枚举实现CaseIterable
enum Types: CaseIterable {
case A
case B
case C
case D
}
然后您可以像这样检查数组中标签的存在
if textField.tag >= 0 && textField.tag < Types.allCases.count { //maybe not needed
if tableViewDataSource.contains(Types.allCases[textField.tag]) {
//do stuff
}
}
另一个选择是使枚举类型为Int
enum Types: Int{
case A = 1
case B
case C
case D
}
然后使用标签直接检查
if let type = Types(rawValue: textField.tag) {
if tableViewDataSource.contains(type) {
//do stuff
}
}
答案 2 :(得分:1)
第二行中的问题是Swift编译器无法确定的隐式类型。简而言之,([.A, .B, .C, .D] as? [Types])
并没有什么好处,您需要在每种类型中都明确使用([Types.A, Types.B, Types.C, Types.D])
。现在,Swift编译器可以将其解释为[Types]
。
在第一个示例中您不需要它,因为您使用了显式类型:
let pickerSelectingFields: [Types] = [.A, .B, .C, .D]
但是通过隐式执行此操作,您会遇到相同的问题:
let pickerSelectingFields: = [.A, .B, .C, .D]
您可以通过提示编译器来再次修复它:
let pickerSelectingFields: = [Types.A, Types.B, Types.C, Types.D]
可能难以解释/理解,但我希望这可以清除一些事情。
还缺少括号,因此最终结果应为:
if (([Types.A, Types.B, Types.C, Types.D]).map { tableViewDataSource.firstIndex(of: $0) }).contains(textField.tag) {
}
答案 3 :(得分:0)
闭包中不包含匿名闭包参数
之所以发生此错误,是因为您不能在if语句的情况下使用结尾块语法。当编译器看到括号{
时,它假定在if
条件为true时,它已经找到要执行的块。 $0
在这种情况下毫无意义。
要解决此问题,必须使用非尾随的块语法,即在map
函数调用中加入括号。
if ([.A, .B, .C, .D] as? [Types]).map ({ tableViewDataSource.firstIndex(of: $0)}).contains(textField.tag)
// ^- here ^-- and here
{
// Do stuff
}
这将使您出现此错误:
表达类型不明确,没有更多上下文
那是因为as?
。通过在此处放置问号,您可以告诉编译器您不确定该数组是否可以转换为Types
的数组,因此它假定该数组没有足够的信息来推断类型。取出问号,编译器知道它必须是Types
的数组,因此可以正确推断表达式的类型。
实际上,如果与这些成员只有一个枚举,则可能会发现您不需要强制转换:
if [.A, .B, .C, .D].map ({ tableViewDataSource.firstIndex(of: $0) }).contains(1)
{
// do something
}
在操场上编译并运行良好。