简写的闭包数组:Xcode Swift:表达式太复杂,无法在合理的时间内解决

Posted

技术标签:

【中文标题】简写的闭包数组:Xcode Swift:表达式太复杂,无法在合理的时间内解决【英文标题】:Array of closures in shorthand: Xcode Swift: Expression too complex to be solved in a reasonable time 【发布时间】:2016-10-09 17:56:19 【问题描述】:

我正在做简单的转换(例如英制到公制)。我创建了一个包含 (String, Closure) 元素的元组数组。这让我可以将一个字符串用于转换(例如“英里到公里”到选择器控件中,并在一行中引用相关的公式,将值传递给转换。我遇到的问题是当我使用 $0 时闭包速记。我收到一个错误“表达式太复杂,无法在合理的时间内解决。”

这是有效的声明和代码:

在初始类语句下面用 ViewController 属性声明:

var formulaTuple = [(convString: String, convFormula: ((Double) -> Double))]()

在 viewDidLoad() 中分配

    formulaTuple = [("miles to kilometers", (a: Double) -> Double in return (a / 0.62137) ),
               ("kilometers to miles", (a: Double) -> Double in return (a * 0.62137) ),
               ("feet to meters", (a: Double) -> Double in return (a / 3.2808) ),
               ("yards to meters", (a: Double) -> Double in return (a / 1.0936) ),
               ("meters to feet", (a: Double) -> Double in return (a * 3.2808) ),
               ("meters to yards", (a: Double) -> Double in return (a * 1.0936) ),
               ("inches to centimeters", (a: Double) -> Double in return (a / 0.39370) ),
               ("centimeters to inches", (a: Double) -> Double in return (a * 0.39370) ),
               ("fahrenheit to celsius", (a: Double) -> Double in return ((a - 32) * (5/9)) ),
               ("celsius to fahrenheit", (a: Double) -> Double in return (a * (9/5) + 32) ),
               ("quarts to liters", (a: Double) -> Double in return (a / 1.05669) ),
               ("liters to quarts", (a: Double) -> Double in return (a * 1.05669) ) ]

代码中的工作调用,其中 row 是选择器中被点击的行,inputValue 是传递的要转换的内容,而 outputValue 是转换的结果。

outputValue = formulaTuple[row].convFormula(inputValue)

当我尝试使用 viewDidLoad() 中的这种语法而不是上面的语法来修剪声明时,就会出现问题:

    formulaTuple = [("miles to kilometers", $0 / 0.62137 ),
                    ("kilometers to miles", $0 * 0.62137 ),
                    ("feet to meters", $0 / 3.2808 ),
                    ("yards to meters", $0 / 1.0936 ),
                    ("meters to feet", $0 * 3.2808 ),
                    ("meters to yards", $0 * 1.0936 ),
                    ("inches to centimeters", $0 / 0.39370),
                    ("centimeters to inches", $0 * 0.39370 ),
                    ("fahrenheit to celsius", ($0 - 32) * (5/9) ),
                    ("celsius to fahrenheit", $0 * (9/5) + 32 ),
                    ("quarts to liters", $0 / 1.05669 ),
                    ("liters to quarts", $0 * 1.05669 ) ]

我认为这会更流畅,但它似乎破坏了 Xcode。想法?我的方法是否从根本上不健全,是否会推荐另一种方法? 谢谢!

【问题讨论】:

【参考方案1】:

当你给它大数组文字然后期望它解释类型时,Swift 表现不佳。在您的情况下,我预计这会起作用,因为您的 formulaTuple 属性已经具有确定的类型。

作为一种解决方法,您可以先初始化一个常量数组,然后将其分配给您的属性:

let temp: [(String, (Double) -> Double)] = [
            ("miles to kilometers", $0 / 0.62137 ),
            ("kilometers to miles", $0 * 0.62137 ),
            ("feet to meters", $0 / 3.2808 ),
            ("yards to meters", $0 / 1.0936 ),
            ("meters to feet", $0 * 3.2808 ),
            ("meters to yards", $0 * 1.0936 ),
            ("inches to centimeters", $0 / 0.39370),
            ("centimeters to inches", $0 * 0.39370 ),
            ("fahrenheit to celsius", ($0 - 32) * (5/9) ),
            ("celsius to fahrenheit", $0 * (9/5) + 32 ),
            ("quarts to liters", $0 / 1.05669 ),
            ("liters to quarts", $0 * 1.05669 )
]

formulaTuple = temp

替代答案

元组实际上是用于临时存储并从函数传回多个结果。您可能需要考虑使用 struct 作为数组值的类型:

struct Conversion 
    let string: String
    let formula: (Double) -> Double


var conversions = [Conversion]()

conversions = [
    Conversion(string: "miles to kilometers", formula: $0 / 0.62137 ),
    Conversion(string: "kilometers to miles", formula: $0 * 0.62137 ),
    Conversion(string: "feet to meters", formula: $0 / 3.2808 ),
    Conversion(string: "yards to meters", formula: $0 / 1.0936 ),
    Conversion(string: "meters to feet", formula: $0 * 3.2808 ),
    Conversion(string: "meters to yards", formula: $0 * 1.0936 ),
    Conversion(string: "inches to centimeters", formula: $0 / 0.39370),
    Conversion(string: "centimeters to inches", formula: $0 * 0.39370 ),
    Conversion(string: "fahrenheit to celsius", formula: ($0 - 32) * (5/9) ),
    Conversion(string: "celsius to fahrenheit", formula: $0 * (9/5) + 32 ),
    Conversion(string: "quarts to liters", formula: $0 / 1.05669 ),
    Conversion(string: "liters to quarts", formula: $0 * 1.05669 )
]

outputValue = conversions[row].formula(inputValue)

Swift 对此更满意,并且不需要 temp 解决方法。

【讨论】:

结构运行得非常好。我重新阅读了关于 Tuples 的 Swift 文档,并更加关注了关于临时类型的内容。非常感谢您的建议、见解和背景。谢谢!

以上是关于简写的闭包数组:Xcode Swift:表达式太复杂,无法在合理的时间内解决的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的尾随闭包语法是啥?

理解 Swift 中 map 函数的简写闭包语法

使用 Xcode LLDB 控制台在 Swift 中调试闭包

如何在 Swift / Xcode 12.3 中重用代码块进行闭包

Swift语法之.map

Swift初见Swift闭包